1 /* Run the Expat test suite
2                             __  __            _
3                          ___\ \/ /_ __   __ _| |_
4                         / _ \\  /| '_ \ / _` | __|
5                        |  __//  \| |_) | (_| | |_
6                         \___/_/\_\ .__/ \__,_|\__|
7                                  |_| XML parser
8 
9    Copyright (c) 2001-2006 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
10    Copyright (c) 2003      Greg Stein <gstein@users.sourceforge.net>
11    Copyright (c) 2005-2007 Steven Solie <steven@solie.ca>
12    Copyright (c) 2005-2012 Karl Waclawek <karl@waclawek.net>
13    Copyright (c) 2016-2022 Sebastian Pipping <sebastian@pipping.org>
14    Copyright (c) 2017-2018 Rhodri James <rhodri@wildebeest.org.uk>
15    Copyright (c) 2017      Joe Orton <jorton@redhat.com>
16    Copyright (c) 2017      José Gutiérrez de la Concha <jose@zeroc.com>
17    Copyright (c) 2018      Marco Maggi <marco.maggi-ipsu@poste.it>
18    Copyright (c) 2019      David Loffredo <loffredo@steptools.com>
19    Copyright (c) 2020      Tim Gates <tim.gates@iress.com>
20    Copyright (c) 2021      Dong-hee Na <donghee.na@python.org>
21    Licensed under the MIT license:
22 
23    Permission is  hereby granted,  free of charge,  to any  person obtaining
24    a  copy  of  this  software   and  associated  documentation  files  (the
25    "Software"),  to  deal in  the  Software  without restriction,  including
26    without  limitation the  rights  to use,  copy,  modify, merge,  publish,
27    distribute, sublicense, and/or sell copies of the Software, and to permit
28    persons  to whom  the Software  is  furnished to  do so,  subject to  the
29    following conditions:
30 
31    The above copyright  notice and this permission notice  shall be included
32    in all copies or substantial portions of the Software.
33 
34    THE  SOFTWARE  IS  PROVIDED  "AS  IS",  WITHOUT  WARRANTY  OF  ANY  KIND,
35    EXPRESS  OR IMPLIED,  INCLUDING  BUT  NOT LIMITED  TO  THE WARRANTIES  OF
36    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
37    NO EVENT SHALL THE AUTHORS OR  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
38    DAMAGES OR  OTHER LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT,  TORT OR
39    OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
40    USE OR OTHER DEALINGS IN THE SOFTWARE.
41 */
42 
43 #include <expat_config.h>
44 
45 #if defined(NDEBUG)
46 #  undef NDEBUG /* because test suite relies on assert(...) at the moment */
47 #endif
48 
49 #include <assert.h>
50 #include <stdlib.h>
51 #include <stdio.h>
52 #include <string.h>
53 #include <stddef.h> /* ptrdiff_t */
54 #include <ctype.h>
55 #include <limits.h>
56 #include <stdint.h> /* intptr_t uint64_t */
57 
58 #if ! defined(__cplusplus)
59 #  include <stdbool.h>
60 #endif
61 
62 #include "expat.h"
63 #include "chardata.h"
64 #include "structdata.h"
65 #include "internal.h"
66 #include "minicheck.h"
67 #include "memcheck.h"
68 #include "siphash.h"
69 #include "ascii.h" /* for ASCII_xxx */
70 
71 #ifdef XML_LARGE_SIZE
72 #  define XML_FMT_INT_MOD "ll"
73 #else
74 #  define XML_FMT_INT_MOD "l"
75 #endif
76 
77 #ifdef XML_UNICODE_WCHAR_T
78 #  define XML_FMT_CHAR "lc"
79 #  define XML_FMT_STR "ls"
80 #  include <wchar.h>
81 #  define xcstrlen(s) wcslen(s)
82 #  define xcstrcmp(s, t) wcscmp((s), (t))
83 #  define xcstrncmp(s, t, n) wcsncmp((s), (t), (n))
84 #  define XCS(s) _XCS(s)
85 #  define _XCS(s) L##s
86 #else
87 #  ifdef XML_UNICODE
88 #    error "No support for UTF-16 character without wchar_t in tests"
89 #  else
90 #    define XML_FMT_CHAR "c"
91 #    define XML_FMT_STR "s"
92 #    define xcstrlen(s) strlen(s)
93 #    define xcstrcmp(s, t) strcmp((s), (t))
94 #    define xcstrncmp(s, t, n) strncmp((s), (t), (n))
95 #    define XCS(s) s
96 #  endif /* XML_UNICODE */
97 #endif   /* XML_UNICODE_WCHAR_T */
98 
99 static XML_Parser g_parser = NULL;
100 
101 static void
tcase_add_test__ifdef_xml_dtd(TCase * tc,tcase_test_function test)102 tcase_add_test__ifdef_xml_dtd(TCase *tc, tcase_test_function test) {
103 #ifdef XML_DTD
104   tcase_add_test(tc, test);
105 #else
106   UNUSED_P(tc);
107   UNUSED_P(test);
108 #endif
109 }
110 
111 static void
basic_setup(void)112 basic_setup(void) {
113   g_parser = XML_ParserCreate(NULL);
114   if (g_parser == NULL)
115     fail("Parser not created.");
116 }
117 
118 static void
basic_teardown(void)119 basic_teardown(void) {
120   if (g_parser != NULL) {
121     XML_ParserFree(g_parser);
122     g_parser = NULL;
123   }
124 }
125 
126 /* Generate a failure using the parser state to create an error message;
127    this should be used when the parser reports an error we weren't
128    expecting.
129 */
130 static void
_xml_failure(XML_Parser parser,const char * file,int line)131 _xml_failure(XML_Parser parser, const char *file, int line) {
132   char buffer[1024];
133   enum XML_Error err = XML_GetErrorCode(parser);
134   sprintf(buffer,
135           "    %d: %" XML_FMT_STR " (line %" XML_FMT_INT_MOD
136           "u, offset %" XML_FMT_INT_MOD "u)\n    reported from %s, line %d\n",
137           err, XML_ErrorString(err), XML_GetCurrentLineNumber(parser),
138           XML_GetCurrentColumnNumber(parser), file, line);
139   _fail_unless(0, file, line, buffer);
140 }
141 
142 static enum XML_Status
_XML_Parse_SINGLE_BYTES(XML_Parser parser,const char * s,int len,int isFinal)143 _XML_Parse_SINGLE_BYTES(XML_Parser parser, const char *s, int len,
144                         int isFinal) {
145   enum XML_Status res = XML_STATUS_ERROR;
146   int offset = 0;
147 
148   if (len == 0) {
149     return XML_Parse(parser, s, len, isFinal);
150   }
151 
152   for (; offset < len; offset++) {
153     const int innerIsFinal = (offset == len - 1) && isFinal;
154     const char c = s[offset]; /* to help out-of-bounds detection */
155     res = XML_Parse(parser, &c, sizeof(char), innerIsFinal);
156     if (res != XML_STATUS_OK) {
157       return res;
158     }
159   }
160   return res;
161 }
162 
163 #define xml_failure(parser) _xml_failure((parser), __FILE__, __LINE__)
164 
165 static void
_expect_failure(const char * text,enum XML_Error errorCode,const char * errorMessage,const char * file,int lineno)166 _expect_failure(const char *text, enum XML_Error errorCode,
167                 const char *errorMessage, const char *file, int lineno) {
168   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
169       == XML_STATUS_OK)
170     /* Hackish use of _fail_unless() macro, but let's us report
171        the right filename and line number. */
172     _fail_unless(0, file, lineno, errorMessage);
173   if (XML_GetErrorCode(g_parser) != errorCode)
174     _xml_failure(g_parser, file, lineno);
175 }
176 
177 #define expect_failure(text, errorCode, errorMessage)                          \
178   _expect_failure((text), (errorCode), (errorMessage), __FILE__, __LINE__)
179 
180 /* Dummy handlers for when we need to set a handler to tickle a bug,
181    but it doesn't need to do anything.
182 */
183 static unsigned long dummy_handler_flags = 0;
184 
185 #define DUMMY_START_DOCTYPE_HANDLER_FLAG (1UL << 0)
186 #define DUMMY_END_DOCTYPE_HANDLER_FLAG (1UL << 1)
187 #define DUMMY_ENTITY_DECL_HANDLER_FLAG (1UL << 2)
188 #define DUMMY_NOTATION_DECL_HANDLER_FLAG (1UL << 3)
189 #define DUMMY_ELEMENT_DECL_HANDLER_FLAG (1UL << 4)
190 #define DUMMY_ATTLIST_DECL_HANDLER_FLAG (1UL << 5)
191 #define DUMMY_COMMENT_HANDLER_FLAG (1UL << 6)
192 #define DUMMY_PI_HANDLER_FLAG (1UL << 7)
193 #define DUMMY_START_ELEMENT_HANDLER_FLAG (1UL << 8)
194 #define DUMMY_START_CDATA_HANDLER_FLAG (1UL << 9)
195 #define DUMMY_END_CDATA_HANDLER_FLAG (1UL << 10)
196 #define DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG (1UL << 11)
197 #define DUMMY_START_NS_DECL_HANDLER_FLAG (1UL << 12)
198 #define DUMMY_END_NS_DECL_HANDLER_FLAG (1UL << 13)
199 #define DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG (1UL << 14)
200 #define DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG (1UL << 15)
201 #define DUMMY_SKIP_HANDLER_FLAG (1UL << 16)
202 #define DUMMY_DEFAULT_HANDLER_FLAG (1UL << 17)
203 
204 static void XMLCALL
dummy_xdecl_handler(void * userData,const XML_Char * version,const XML_Char * encoding,int standalone)205 dummy_xdecl_handler(void *userData, const XML_Char *version,
206                     const XML_Char *encoding, int standalone) {
207   UNUSED_P(userData);
208   UNUSED_P(version);
209   UNUSED_P(encoding);
210   UNUSED_P(standalone);
211 }
212 
213 static void XMLCALL
dummy_start_doctype_handler(void * userData,const XML_Char * doctypeName,const XML_Char * sysid,const XML_Char * pubid,int has_internal_subset)214 dummy_start_doctype_handler(void *userData, const XML_Char *doctypeName,
215                             const XML_Char *sysid, const XML_Char *pubid,
216                             int has_internal_subset) {
217   UNUSED_P(userData);
218   UNUSED_P(doctypeName);
219   UNUSED_P(sysid);
220   UNUSED_P(pubid);
221   UNUSED_P(has_internal_subset);
222   dummy_handler_flags |= DUMMY_START_DOCTYPE_HANDLER_FLAG;
223 }
224 
225 static void XMLCALL
dummy_end_doctype_handler(void * userData)226 dummy_end_doctype_handler(void *userData) {
227   UNUSED_P(userData);
228   dummy_handler_flags |= DUMMY_END_DOCTYPE_HANDLER_FLAG;
229 }
230 
231 static void XMLCALL
dummy_entity_decl_handler(void * userData,const XML_Char * entityName,int is_parameter_entity,const XML_Char * value,int value_length,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId,const XML_Char * notationName)232 dummy_entity_decl_handler(void *userData, const XML_Char *entityName,
233                           int is_parameter_entity, const XML_Char *value,
234                           int value_length, const XML_Char *base,
235                           const XML_Char *systemId, const XML_Char *publicId,
236                           const XML_Char *notationName) {
237   UNUSED_P(userData);
238   UNUSED_P(entityName);
239   UNUSED_P(is_parameter_entity);
240   UNUSED_P(value);
241   UNUSED_P(value_length);
242   UNUSED_P(base);
243   UNUSED_P(systemId);
244   UNUSED_P(publicId);
245   UNUSED_P(notationName);
246   dummy_handler_flags |= DUMMY_ENTITY_DECL_HANDLER_FLAG;
247 }
248 
249 static void XMLCALL
dummy_notation_decl_handler(void * userData,const XML_Char * notationName,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)250 dummy_notation_decl_handler(void *userData, const XML_Char *notationName,
251                             const XML_Char *base, const XML_Char *systemId,
252                             const XML_Char *publicId) {
253   UNUSED_P(userData);
254   UNUSED_P(notationName);
255   UNUSED_P(base);
256   UNUSED_P(systemId);
257   UNUSED_P(publicId);
258   dummy_handler_flags |= DUMMY_NOTATION_DECL_HANDLER_FLAG;
259 }
260 
261 static void XMLCALL
dummy_element_decl_handler(void * userData,const XML_Char * name,XML_Content * model)262 dummy_element_decl_handler(void *userData, const XML_Char *name,
263                            XML_Content *model) {
264   UNUSED_P(userData);
265   UNUSED_P(name);
266   /* The content model must be freed by the handler.  Unfortunately
267    * we cannot pass the parser as the userData because this is used
268    * with other handlers that require other userData.
269    */
270   XML_FreeContentModel(g_parser, model);
271   dummy_handler_flags |= DUMMY_ELEMENT_DECL_HANDLER_FLAG;
272 }
273 
274 static void XMLCALL
dummy_attlist_decl_handler(void * userData,const XML_Char * elname,const XML_Char * attname,const XML_Char * att_type,const XML_Char * dflt,int isrequired)275 dummy_attlist_decl_handler(void *userData, const XML_Char *elname,
276                            const XML_Char *attname, const XML_Char *att_type,
277                            const XML_Char *dflt, int isrequired) {
278   UNUSED_P(userData);
279   UNUSED_P(elname);
280   UNUSED_P(attname);
281   UNUSED_P(att_type);
282   UNUSED_P(dflt);
283   UNUSED_P(isrequired);
284   dummy_handler_flags |= DUMMY_ATTLIST_DECL_HANDLER_FLAG;
285 }
286 
287 static void XMLCALL
dummy_comment_handler(void * userData,const XML_Char * data)288 dummy_comment_handler(void *userData, const XML_Char *data) {
289   UNUSED_P(userData);
290   UNUSED_P(data);
291   dummy_handler_flags |= DUMMY_COMMENT_HANDLER_FLAG;
292 }
293 
294 static void XMLCALL
dummy_pi_handler(void * userData,const XML_Char * target,const XML_Char * data)295 dummy_pi_handler(void *userData, const XML_Char *target, const XML_Char *data) {
296   UNUSED_P(userData);
297   UNUSED_P(target);
298   UNUSED_P(data);
299   dummy_handler_flags |= DUMMY_PI_HANDLER_FLAG;
300 }
301 
302 static void XMLCALL
dummy_start_element(void * userData,const XML_Char * name,const XML_Char ** atts)303 dummy_start_element(void *userData, const XML_Char *name,
304                     const XML_Char **atts) {
305   UNUSED_P(userData);
306   UNUSED_P(name);
307   UNUSED_P(atts);
308   dummy_handler_flags |= DUMMY_START_ELEMENT_HANDLER_FLAG;
309 }
310 
311 static void XMLCALL
dummy_end_element(void * userData,const XML_Char * name)312 dummy_end_element(void *userData, const XML_Char *name) {
313   UNUSED_P(userData);
314   UNUSED_P(name);
315 }
316 
317 static void XMLCALL
dummy_start_cdata_handler(void * userData)318 dummy_start_cdata_handler(void *userData) {
319   UNUSED_P(userData);
320   dummy_handler_flags |= DUMMY_START_CDATA_HANDLER_FLAG;
321 }
322 
323 static void XMLCALL
dummy_end_cdata_handler(void * userData)324 dummy_end_cdata_handler(void *userData) {
325   UNUSED_P(userData);
326   dummy_handler_flags |= DUMMY_END_CDATA_HANDLER_FLAG;
327 }
328 
329 static void XMLCALL
dummy_cdata_handler(void * userData,const XML_Char * s,int len)330 dummy_cdata_handler(void *userData, const XML_Char *s, int len) {
331   UNUSED_P(userData);
332   UNUSED_P(s);
333   UNUSED_P(len);
334 }
335 
336 static void XMLCALL
dummy_start_namespace_decl_handler(void * userData,const XML_Char * prefix,const XML_Char * uri)337 dummy_start_namespace_decl_handler(void *userData, const XML_Char *prefix,
338                                    const XML_Char *uri) {
339   UNUSED_P(userData);
340   UNUSED_P(prefix);
341   UNUSED_P(uri);
342   dummy_handler_flags |= DUMMY_START_NS_DECL_HANDLER_FLAG;
343 }
344 
345 static void XMLCALL
dummy_end_namespace_decl_handler(void * userData,const XML_Char * prefix)346 dummy_end_namespace_decl_handler(void *userData, const XML_Char *prefix) {
347   UNUSED_P(userData);
348   UNUSED_P(prefix);
349   dummy_handler_flags |= DUMMY_END_NS_DECL_HANDLER_FLAG;
350 }
351 
352 /* This handler is obsolete, but while the code exists we should
353  * ensure that dealing with the handler is covered by tests.
354  */
355 static void XMLCALL
dummy_unparsed_entity_decl_handler(void * userData,const XML_Char * entityName,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId,const XML_Char * notationName)356 dummy_unparsed_entity_decl_handler(void *userData, const XML_Char *entityName,
357                                    const XML_Char *base,
358                                    const XML_Char *systemId,
359                                    const XML_Char *publicId,
360                                    const XML_Char *notationName) {
361   UNUSED_P(userData);
362   UNUSED_P(entityName);
363   UNUSED_P(base);
364   UNUSED_P(systemId);
365   UNUSED_P(publicId);
366   UNUSED_P(notationName);
367   dummy_handler_flags |= DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG;
368 }
369 
370 static void XMLCALL
dummy_default_handler(void * userData,const XML_Char * s,int len)371 dummy_default_handler(void *userData, const XML_Char *s, int len) {
372   UNUSED_P(userData);
373   UNUSED_P(s);
374   UNUSED_P(len);
375 }
376 
377 static void XMLCALL
dummy_start_doctype_decl_handler(void * userData,const XML_Char * doctypeName,const XML_Char * sysid,const XML_Char * pubid,int has_internal_subset)378 dummy_start_doctype_decl_handler(void *userData, const XML_Char *doctypeName,
379                                  const XML_Char *sysid, const XML_Char *pubid,
380                                  int has_internal_subset) {
381   UNUSED_P(userData);
382   UNUSED_P(doctypeName);
383   UNUSED_P(sysid);
384   UNUSED_P(pubid);
385   UNUSED_P(has_internal_subset);
386   dummy_handler_flags |= DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG;
387 }
388 
389 static void XMLCALL
dummy_end_doctype_decl_handler(void * userData)390 dummy_end_doctype_decl_handler(void *userData) {
391   UNUSED_P(userData);
392   dummy_handler_flags |= DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG;
393 }
394 
395 static void XMLCALL
dummy_skip_handler(void * userData,const XML_Char * entityName,int is_parameter_entity)396 dummy_skip_handler(void *userData, const XML_Char *entityName,
397                    int is_parameter_entity) {
398   UNUSED_P(userData);
399   UNUSED_P(entityName);
400   UNUSED_P(is_parameter_entity);
401   dummy_handler_flags |= DUMMY_SKIP_HANDLER_FLAG;
402 }
403 
404 /* Useful external entity handler */
405 typedef struct ExtOption {
406   const XML_Char *system_id;
407   const char *parse_text;
408 } ExtOption;
409 
410 static int XMLCALL
external_entity_optioner(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)411 external_entity_optioner(XML_Parser parser, const XML_Char *context,
412                          const XML_Char *base, const XML_Char *systemId,
413                          const XML_Char *publicId) {
414   ExtOption *options = (ExtOption *)XML_GetUserData(parser);
415   XML_Parser ext_parser;
416 
417   UNUSED_P(base);
418   UNUSED_P(publicId);
419   while (options->parse_text != NULL) {
420     if (! xcstrcmp(systemId, options->system_id)) {
421       enum XML_Status rc;
422       ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
423       if (ext_parser == NULL)
424         return XML_STATUS_ERROR;
425       rc = _XML_Parse_SINGLE_BYTES(ext_parser, options->parse_text,
426                                    (int)strlen(options->parse_text), XML_TRUE);
427       XML_ParserFree(ext_parser);
428       return rc;
429     }
430     options++;
431   }
432   fail("No suitable option found");
433   return XML_STATUS_ERROR;
434 }
435 
436 /*
437  * Parameter entity evaluation support.
438  */
439 #define ENTITY_MATCH_FAIL (-1)
440 #define ENTITY_MATCH_NOT_FOUND (0)
441 #define ENTITY_MATCH_SUCCESS (1)
442 static const XML_Char *entity_name_to_match = NULL;
443 static const XML_Char *entity_value_to_match = NULL;
444 static int entity_match_flag = ENTITY_MATCH_NOT_FOUND;
445 
446 static void XMLCALL
param_entity_match_handler(void * userData,const XML_Char * entityName,int is_parameter_entity,const XML_Char * value,int value_length,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId,const XML_Char * notationName)447 param_entity_match_handler(void *userData, const XML_Char *entityName,
448                            int is_parameter_entity, const XML_Char *value,
449                            int value_length, const XML_Char *base,
450                            const XML_Char *systemId, const XML_Char *publicId,
451                            const XML_Char *notationName) {
452   UNUSED_P(userData);
453   UNUSED_P(base);
454   UNUSED_P(systemId);
455   UNUSED_P(publicId);
456   UNUSED_P(notationName);
457   if (! is_parameter_entity || entity_name_to_match == NULL
458       || entity_value_to_match == NULL) {
459     return;
460   }
461   if (! xcstrcmp(entityName, entity_name_to_match)) {
462     /* The cast here is safe because we control the horizontal and
463      * the vertical, and we therefore know our strings are never
464      * going to overflow an int.
465      */
466     if (value_length != (int)xcstrlen(entity_value_to_match)
467         || xcstrncmp(value, entity_value_to_match, value_length)) {
468       entity_match_flag = ENTITY_MATCH_FAIL;
469     } else {
470       entity_match_flag = ENTITY_MATCH_SUCCESS;
471     }
472   }
473   /* Else leave the match flag alone */
474 }
475 
476 /*
477  * Character & encoding tests.
478  */
479 
START_TEST(test_nul_byte)480 START_TEST(test_nul_byte) {
481   char text[] = "<doc>\0</doc>";
482 
483   /* test that a NUL byte (in US-ASCII data) is an error */
484   if (_XML_Parse_SINGLE_BYTES(g_parser, text, sizeof(text) - 1, XML_TRUE)
485       == XML_STATUS_OK)
486     fail("Parser did not report error on NUL-byte.");
487   if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
488     xml_failure(g_parser);
489 }
490 END_TEST
491 
START_TEST(test_u0000_char)492 START_TEST(test_u0000_char) {
493   /* test that a NUL byte (in US-ASCII data) is an error */
494   expect_failure("<doc>&#0;</doc>", XML_ERROR_BAD_CHAR_REF,
495                  "Parser did not report error on NUL-byte.");
496 }
497 END_TEST
498 
START_TEST(test_siphash_self)499 START_TEST(test_siphash_self) {
500   if (! sip24_valid())
501     fail("SipHash self-test failed");
502 }
503 END_TEST
504 
START_TEST(test_siphash_spec)505 START_TEST(test_siphash_spec) {
506   /* https://131002.net/siphash/siphash.pdf (page 19, "Test values") */
507   const char message[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09"
508                          "\x0a\x0b\x0c\x0d\x0e";
509   const size_t len = sizeof(message) - 1;
510   const uint64_t expected = _SIP_ULL(0xa129ca61U, 0x49be45e5U);
511   struct siphash state;
512   struct sipkey key;
513 
514   sip_tokey(&key, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09"
515                   "\x0a\x0b\x0c\x0d\x0e\x0f");
516   sip24_init(&state, &key);
517 
518   /* Cover spread across calls */
519   sip24_update(&state, message, 4);
520   sip24_update(&state, message + 4, len - 4);
521 
522   /* Cover null length */
523   sip24_update(&state, message, 0);
524 
525   if (sip24_final(&state) != expected)
526     fail("sip24_final failed spec test\n");
527 
528   /* Cover wrapper */
529   if (siphash24(message, len, &key) != expected)
530     fail("siphash24 failed spec test\n");
531 }
532 END_TEST
533 
START_TEST(test_bom_utf8)534 START_TEST(test_bom_utf8) {
535   /* This test is really just making sure we don't core on a UTF-8 BOM. */
536   const char *text = "\357\273\277<e/>";
537 
538   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
539       == XML_STATUS_ERROR)
540     xml_failure(g_parser);
541 }
542 END_TEST
543 
START_TEST(test_bom_utf16_be)544 START_TEST(test_bom_utf16_be) {
545   char text[] = "\376\377\0<\0e\0/\0>";
546 
547   if (_XML_Parse_SINGLE_BYTES(g_parser, text, sizeof(text) - 1, XML_TRUE)
548       == XML_STATUS_ERROR)
549     xml_failure(g_parser);
550 }
551 END_TEST
552 
START_TEST(test_bom_utf16_le)553 START_TEST(test_bom_utf16_le) {
554   char text[] = "\377\376<\0e\0/\0>\0";
555 
556   if (_XML_Parse_SINGLE_BYTES(g_parser, text, sizeof(text) - 1, XML_TRUE)
557       == XML_STATUS_ERROR)
558     xml_failure(g_parser);
559 }
560 END_TEST
561 
562 /* Parse whole buffer at once to exercise a different code path */
START_TEST(test_nobom_utf16_le)563 START_TEST(test_nobom_utf16_le) {
564   char text[] = " \0<\0e\0/\0>\0";
565 
566   if (XML_Parse(g_parser, text, sizeof(text) - 1, XML_TRUE) == XML_STATUS_ERROR)
567     xml_failure(g_parser);
568 }
569 END_TEST
570 
571 static void XMLCALL
accumulate_characters(void * userData,const XML_Char * s,int len)572 accumulate_characters(void *userData, const XML_Char *s, int len) {
573   CharData_AppendXMLChars((CharData *)userData, s, len);
574 }
575 
576 static void XMLCALL
accumulate_attribute(void * userData,const XML_Char * name,const XML_Char ** atts)577 accumulate_attribute(void *userData, const XML_Char *name,
578                      const XML_Char **atts) {
579   CharData *storage = (CharData *)userData;
580   UNUSED_P(name);
581   /* Check there are attributes to deal with */
582   if (atts == NULL)
583     return;
584 
585   while (storage->count < 0 && atts[0] != NULL) {
586     /* "accumulate" the value of the first attribute we see */
587     CharData_AppendXMLChars(storage, atts[1], -1);
588     atts += 2;
589   }
590 }
591 
592 static void
_run_character_check(const char * text,const XML_Char * expected,const char * file,int line)593 _run_character_check(const char *text, const XML_Char *expected,
594                      const char *file, int line) {
595   CharData storage;
596 
597   CharData_Init(&storage);
598   XML_SetUserData(g_parser, &storage);
599   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
600   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
601       == XML_STATUS_ERROR)
602     _xml_failure(g_parser, file, line);
603   CharData_CheckXMLChars(&storage, expected);
604 }
605 
606 #define run_character_check(text, expected)                                    \
607   _run_character_check(text, expected, __FILE__, __LINE__)
608 
609 static void
_run_attribute_check(const char * text,const XML_Char * expected,const char * file,int line)610 _run_attribute_check(const char *text, const XML_Char *expected,
611                      const char *file, int line) {
612   CharData storage;
613 
614   CharData_Init(&storage);
615   XML_SetUserData(g_parser, &storage);
616   XML_SetStartElementHandler(g_parser, accumulate_attribute);
617   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
618       == XML_STATUS_ERROR)
619     _xml_failure(g_parser, file, line);
620   CharData_CheckXMLChars(&storage, expected);
621 }
622 
623 #define run_attribute_check(text, expected)                                    \
624   _run_attribute_check(text, expected, __FILE__, __LINE__)
625 
626 typedef struct ExtTest {
627   const char *parse_text;
628   const XML_Char *encoding;
629   CharData *storage;
630 } ExtTest;
631 
632 static void XMLCALL
ext_accumulate_characters(void * userData,const XML_Char * s,int len)633 ext_accumulate_characters(void *userData, const XML_Char *s, int len) {
634   ExtTest *test_data = (ExtTest *)userData;
635   accumulate_characters(test_data->storage, s, len);
636 }
637 
638 static void
_run_ext_character_check(const char * text,ExtTest * test_data,const XML_Char * expected,const char * file,int line)639 _run_ext_character_check(const char *text, ExtTest *test_data,
640                          const XML_Char *expected, const char *file, int line) {
641   CharData *const storage = (CharData *)malloc(sizeof(CharData));
642 
643   CharData_Init(storage);
644   test_data->storage = storage;
645   XML_SetUserData(g_parser, test_data);
646   XML_SetCharacterDataHandler(g_parser, ext_accumulate_characters);
647   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
648       == XML_STATUS_ERROR)
649     _xml_failure(g_parser, file, line);
650   CharData_CheckXMLChars(storage, expected);
651 
652   free(storage);
653 }
654 
655 #define run_ext_character_check(text, test_data, expected)                     \
656   _run_ext_character_check(text, test_data, expected, __FILE__, __LINE__)
657 
658 /* Regression test for SF bug #491986. */
START_TEST(test_danish_latin1)659 START_TEST(test_danish_latin1) {
660   const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
661                      "<e>J\xF8rgen \xE6\xF8\xE5\xC6\xD8\xC5</e>";
662 #ifdef XML_UNICODE
663   const XML_Char *expected
664       = XCS("J\x00f8rgen \x00e6\x00f8\x00e5\x00c6\x00d8\x00c5");
665 #else
666   const XML_Char *expected
667       = XCS("J\xC3\xB8rgen \xC3\xA6\xC3\xB8\xC3\xA5\xC3\x86\xC3\x98\xC3\x85");
668 #endif
669   run_character_check(text, expected);
670 }
671 END_TEST
672 
673 /* Regression test for SF bug #514281. */
START_TEST(test_french_charref_hexidecimal)674 START_TEST(test_french_charref_hexidecimal) {
675   const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
676                      "<doc>&#xE9;&#xE8;&#xE0;&#xE7;&#xEA;&#xC8;</doc>";
677 #ifdef XML_UNICODE
678   const XML_Char *expected = XCS("\x00e9\x00e8\x00e0\x00e7\x00ea\x00c8");
679 #else
680   const XML_Char *expected
681       = XCS("\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88");
682 #endif
683   run_character_check(text, expected);
684 }
685 END_TEST
686 
START_TEST(test_french_charref_decimal)687 START_TEST(test_french_charref_decimal) {
688   const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
689                      "<doc>&#233;&#232;&#224;&#231;&#234;&#200;</doc>";
690 #ifdef XML_UNICODE
691   const XML_Char *expected = XCS("\x00e9\x00e8\x00e0\x00e7\x00ea\x00c8");
692 #else
693   const XML_Char *expected
694       = XCS("\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88");
695 #endif
696   run_character_check(text, expected);
697 }
698 END_TEST
699 
START_TEST(test_french_latin1)700 START_TEST(test_french_latin1) {
701   const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
702                      "<doc>\xE9\xE8\xE0\xE7\xEa\xC8</doc>";
703 #ifdef XML_UNICODE
704   const XML_Char *expected = XCS("\x00e9\x00e8\x00e0\x00e7\x00ea\x00c8");
705 #else
706   const XML_Char *expected
707       = XCS("\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88");
708 #endif
709   run_character_check(text, expected);
710 }
711 END_TEST
712 
START_TEST(test_french_utf8)713 START_TEST(test_french_utf8) {
714   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
715                      "<doc>\xC3\xA9</doc>";
716 #ifdef XML_UNICODE
717   const XML_Char *expected = XCS("\x00e9");
718 #else
719   const XML_Char *expected = XCS("\xC3\xA9");
720 #endif
721   run_character_check(text, expected);
722 }
723 END_TEST
724 
725 /* Regression test for SF bug #600479.
726    XXX There should be a test that exercises all legal XML Unicode
727    characters as PCDATA and attribute value content, and XML Name
728    characters as part of element and attribute names.
729 */
START_TEST(test_utf8_false_rejection)730 START_TEST(test_utf8_false_rejection) {
731   const char *text = "<doc>\xEF\xBA\xBF</doc>";
732 #ifdef XML_UNICODE
733   const XML_Char *expected = XCS("\xfebf");
734 #else
735   const XML_Char *expected = XCS("\xEF\xBA\xBF");
736 #endif
737   run_character_check(text, expected);
738 }
739 END_TEST
740 
741 /* Regression test for SF bug #477667.
742    This test assures that any 8-bit character followed by a 7-bit
743    character will not be mistakenly interpreted as a valid UTF-8
744    sequence.
745 */
START_TEST(test_illegal_utf8)746 START_TEST(test_illegal_utf8) {
747   char text[100];
748   int i;
749 
750   for (i = 128; i <= 255; ++i) {
751     sprintf(text, "<e>%ccd</e>", i);
752     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
753         == XML_STATUS_OK) {
754       sprintf(text, "expected token error for '%c' (ordinal %d) in UTF-8 text",
755               i, i);
756       fail(text);
757     } else if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
758       xml_failure(g_parser);
759     /* Reset the parser since we use the same parser repeatedly. */
760     XML_ParserReset(g_parser, NULL);
761   }
762 }
763 END_TEST
764 
765 /* Examples, not masks: */
766 #define UTF8_LEAD_1 "\x7f" /* 0b01111111 */
767 #define UTF8_LEAD_2 "\xdf" /* 0b11011111 */
768 #define UTF8_LEAD_3 "\xef" /* 0b11101111 */
769 #define UTF8_LEAD_4 "\xf7" /* 0b11110111 */
770 #define UTF8_FOLLOW "\xbf" /* 0b10111111 */
771 
START_TEST(test_utf8_auto_align)772 START_TEST(test_utf8_auto_align) {
773   struct TestCase {
774     ptrdiff_t expectedMovementInChars;
775     const char *input;
776   };
777 
778   struct TestCase cases[] = {
779       {00, ""},
780 
781       {00, UTF8_LEAD_1},
782 
783       {-1, UTF8_LEAD_2},
784       {00, UTF8_LEAD_2 UTF8_FOLLOW},
785 
786       {-1, UTF8_LEAD_3},
787       {-2, UTF8_LEAD_3 UTF8_FOLLOW},
788       {00, UTF8_LEAD_3 UTF8_FOLLOW UTF8_FOLLOW},
789 
790       {-1, UTF8_LEAD_4},
791       {-2, UTF8_LEAD_4 UTF8_FOLLOW},
792       {-3, UTF8_LEAD_4 UTF8_FOLLOW UTF8_FOLLOW},
793       {00, UTF8_LEAD_4 UTF8_FOLLOW UTF8_FOLLOW UTF8_FOLLOW},
794   };
795 
796   size_t i = 0;
797   bool success = true;
798   for (; i < sizeof(cases) / sizeof(*cases); i++) {
799     const char *fromLim = cases[i].input + strlen(cases[i].input);
800     const char *const fromLimInitially = fromLim;
801     ptrdiff_t actualMovementInChars;
802 
803     _INTERNAL_trim_to_complete_utf8_characters(cases[i].input, &fromLim);
804 
805     actualMovementInChars = (fromLim - fromLimInitially);
806     if (actualMovementInChars != cases[i].expectedMovementInChars) {
807       size_t j = 0;
808       success = false;
809       printf("[-] UTF-8 case %2u: Expected movement by %2d chars"
810              ", actually moved by %2d chars: \"",
811              (unsigned)(i + 1), (int)cases[i].expectedMovementInChars,
812              (int)actualMovementInChars);
813       for (; j < strlen(cases[i].input); j++) {
814         printf("\\x%02x", (unsigned char)cases[i].input[j]);
815       }
816       printf("\"\n");
817     }
818   }
819 
820   if (! success) {
821     fail("UTF-8 auto-alignment is not bullet-proof\n");
822   }
823 }
824 END_TEST
825 
START_TEST(test_utf16)826 START_TEST(test_utf16) {
827   /* <?xml version="1.0" encoding="UTF-16"?>
828    *  <doc a='123'>some {A} text</doc>
829    *
830    * where {A} is U+FF21, FULLWIDTH LATIN CAPITAL LETTER A
831    */
832   char text[]
833       = "\000<\000?\000x\000m\000\154\000 \000v\000e\000r\000s\000i\000o"
834         "\000n\000=\000'\0001\000.\000\060\000'\000 \000e\000n\000c\000o"
835         "\000d\000i\000n\000g\000=\000'\000U\000T\000F\000-\0001\000\066"
836         "\000'\000?\000>\000\n"
837         "\000<\000d\000o\000c\000 \000a\000=\000'\0001\0002\0003\000'\000>"
838         "\000s\000o\000m\000e\000 \xff\x21\000 \000t\000e\000x\000t\000"
839         "<\000/\000d\000o\000c\000>";
840 #ifdef XML_UNICODE
841   const XML_Char *expected = XCS("some \xff21 text");
842 #else
843   const XML_Char *expected = XCS("some \357\274\241 text");
844 #endif
845   CharData storage;
846 
847   CharData_Init(&storage);
848   XML_SetUserData(g_parser, &storage);
849   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
850   if (_XML_Parse_SINGLE_BYTES(g_parser, text, sizeof(text) - 1, XML_TRUE)
851       == XML_STATUS_ERROR)
852     xml_failure(g_parser);
853   CharData_CheckXMLChars(&storage, expected);
854 }
855 END_TEST
856 
START_TEST(test_utf16_le_epilog_newline)857 START_TEST(test_utf16_le_epilog_newline) {
858   unsigned int first_chunk_bytes = 17;
859   char text[] = "\xFF\xFE"                  /* BOM */
860                 "<\000e\000/\000>\000"      /* document element */
861                 "\r\000\n\000\r\000\n\000"; /* epilog */
862 
863   if (first_chunk_bytes >= sizeof(text) - 1)
864     fail("bad value of first_chunk_bytes");
865   if (_XML_Parse_SINGLE_BYTES(g_parser, text, first_chunk_bytes, XML_FALSE)
866       == XML_STATUS_ERROR)
867     xml_failure(g_parser);
868   else {
869     enum XML_Status rc;
870     rc = _XML_Parse_SINGLE_BYTES(g_parser, text + first_chunk_bytes,
871                                  sizeof(text) - first_chunk_bytes - 1,
872                                  XML_TRUE);
873     if (rc == XML_STATUS_ERROR)
874       xml_failure(g_parser);
875   }
876 }
877 END_TEST
878 
879 /* Test that an outright lie in the encoding is faulted */
START_TEST(test_not_utf16)880 START_TEST(test_not_utf16) {
881   const char *text = "<?xml version='1.0' encoding='utf-16'?>"
882                      "<doc>Hi</doc>";
883 
884   /* Use a handler to provoke the appropriate code paths */
885   XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler);
886   expect_failure(text, XML_ERROR_INCORRECT_ENCODING,
887                  "UTF-16 declared in UTF-8 not faulted");
888 }
889 END_TEST
890 
891 /* Test that an unknown encoding is rejected */
START_TEST(test_bad_encoding)892 START_TEST(test_bad_encoding) {
893   const char *text = "<doc>Hi</doc>";
894 
895   if (! XML_SetEncoding(g_parser, XCS("unknown-encoding")))
896     fail("XML_SetEncoding failed");
897   expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
898                  "Unknown encoding not faulted");
899 }
900 END_TEST
901 
902 /* Regression test for SF bug #481609, #774028. */
START_TEST(test_latin1_umlauts)903 START_TEST(test_latin1_umlauts) {
904   const char *text
905       = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
906         "<e a='\xE4 \xF6 \xFC &#228; &#246; &#252; &#x00E4; &#x0F6; &#xFC; >'\n"
907         "  >\xE4 \xF6 \xFC &#228; &#246; &#252; &#x00E4; &#x0F6; &#xFC; ></e>";
908 #ifdef XML_UNICODE
909   /* Expected results in UTF-16 */
910   const XML_Char *expected = XCS("\x00e4 \x00f6 \x00fc ")
911       XCS("\x00e4 \x00f6 \x00fc ") XCS("\x00e4 \x00f6 \x00fc >");
912 #else
913   /* Expected results in UTF-8 */
914   const XML_Char *expected = XCS("\xC3\xA4 \xC3\xB6 \xC3\xBC ")
915       XCS("\xC3\xA4 \xC3\xB6 \xC3\xBC ") XCS("\xC3\xA4 \xC3\xB6 \xC3\xBC >");
916 #endif
917 
918   run_character_check(text, expected);
919   XML_ParserReset(g_parser, NULL);
920   run_attribute_check(text, expected);
921   /* Repeat with a default handler */
922   XML_ParserReset(g_parser, NULL);
923   XML_SetDefaultHandler(g_parser, dummy_default_handler);
924   run_character_check(text, expected);
925   XML_ParserReset(g_parser, NULL);
926   XML_SetDefaultHandler(g_parser, dummy_default_handler);
927   run_attribute_check(text, expected);
928 }
929 END_TEST
930 
931 /* Test that an element name with a 4-byte UTF-8 character is rejected */
START_TEST(test_long_utf8_character)932 START_TEST(test_long_utf8_character) {
933   const char *text
934       = "<?xml version='1.0' encoding='utf-8'?>\n"
935         /* 0xf0 0x90 0x80 0x80 = U+10000, the first Linear B character */
936         "<do\xf0\x90\x80\x80/>";
937   expect_failure(text, XML_ERROR_INVALID_TOKEN,
938                  "4-byte UTF-8 character in element name not faulted");
939 }
940 END_TEST
941 
942 /* Test that a long latin-1 attribute (too long to convert in one go)
943  * is correctly converted
944  */
START_TEST(test_long_latin1_attribute)945 START_TEST(test_long_latin1_attribute) {
946   const char *text
947       = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
948         "<doc att='"
949         /* 64 characters per line */
950         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
951         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
952         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
953         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
954         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
955         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
956         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
957         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
958         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
959         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
960         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
961         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
962         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
963         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
964         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
965         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
966         /* Last character splits across a buffer boundary */
967         "\xe4'>\n</doc>";
968 
969   const XML_Char *expected =
970       /* 64 characters per line */
971       /* clang-format off */
972         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
973         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
974         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
975         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
976         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
977         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
978         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
979         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
980         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
981         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
982         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
983         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
984         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
985         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
986         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
987         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO")
988   /* clang-format on */
989 #ifdef XML_UNICODE
990                                                   XCS("\x00e4");
991 #else
992                                                   XCS("\xc3\xa4");
993 #endif
994 
995   run_attribute_check(text, expected);
996 }
997 END_TEST
998 
999 /* Test that a long ASCII attribute (too long to convert in one go)
1000  * is correctly converted
1001  */
START_TEST(test_long_ascii_attribute)1002 START_TEST(test_long_ascii_attribute) {
1003   const char *text
1004       = "<?xml version='1.0' encoding='us-ascii'?>\n"
1005         "<doc att='"
1006         /* 64 characters per line */
1007         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1008         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1009         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1010         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1011         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1012         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1013         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1014         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1015         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1016         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1017         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1018         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1019         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1020         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1021         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1022         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1023         "01234'>\n</doc>";
1024   const XML_Char *expected =
1025       /* 64 characters per line */
1026       /* clang-format off */
1027         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1028         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1029         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1030         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1031         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1032         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1033         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1034         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1035         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1036         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1037         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1038         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1039         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1040         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1041         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1042         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1043         XCS("01234");
1044   /* clang-format on */
1045 
1046   run_attribute_check(text, expected);
1047 }
1048 END_TEST
1049 
1050 /* Regression test #1 for SF bug #653180. */
START_TEST(test_line_number_after_parse)1051 START_TEST(test_line_number_after_parse) {
1052   const char *text = "<tag>\n"
1053                      "\n"
1054                      "\n</tag>";
1055   XML_Size lineno;
1056 
1057   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
1058       == XML_STATUS_ERROR)
1059     xml_failure(g_parser);
1060   lineno = XML_GetCurrentLineNumber(g_parser);
1061   if (lineno != 4) {
1062     char buffer[100];
1063     sprintf(buffer, "expected 4 lines, saw %" XML_FMT_INT_MOD "u", lineno);
1064     fail(buffer);
1065   }
1066 }
1067 END_TEST
1068 
1069 /* Regression test #2 for SF bug #653180. */
START_TEST(test_column_number_after_parse)1070 START_TEST(test_column_number_after_parse) {
1071   const char *text = "<tag></tag>";
1072   XML_Size colno;
1073 
1074   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
1075       == XML_STATUS_ERROR)
1076     xml_failure(g_parser);
1077   colno = XML_GetCurrentColumnNumber(g_parser);
1078   if (colno != 11) {
1079     char buffer[100];
1080     sprintf(buffer, "expected 11 columns, saw %" XML_FMT_INT_MOD "u", colno);
1081     fail(buffer);
1082   }
1083 }
1084 END_TEST
1085 
1086 #define STRUCT_START_TAG 0
1087 #define STRUCT_END_TAG 1
1088 static void XMLCALL
start_element_event_handler2(void * userData,const XML_Char * name,const XML_Char ** attr)1089 start_element_event_handler2(void *userData, const XML_Char *name,
1090                              const XML_Char **attr) {
1091   StructData *storage = (StructData *)userData;
1092   UNUSED_P(attr);
1093   StructData_AddItem(storage, name, XML_GetCurrentColumnNumber(g_parser),
1094                      XML_GetCurrentLineNumber(g_parser), STRUCT_START_TAG);
1095 }
1096 
1097 static void XMLCALL
end_element_event_handler2(void * userData,const XML_Char * name)1098 end_element_event_handler2(void *userData, const XML_Char *name) {
1099   StructData *storage = (StructData *)userData;
1100   StructData_AddItem(storage, name, XML_GetCurrentColumnNumber(g_parser),
1101                      XML_GetCurrentLineNumber(g_parser), STRUCT_END_TAG);
1102 }
1103 
1104 /* Regression test #3 for SF bug #653180. */
START_TEST(test_line_and_column_numbers_inside_handlers)1105 START_TEST(test_line_and_column_numbers_inside_handlers) {
1106   const char *text = "<a>\n"      /* Unix end-of-line */
1107                      "  <b>\r\n"  /* Windows end-of-line */
1108                      "    <c/>\r" /* Mac OS end-of-line */
1109                      "  </b>\n"
1110                      "  <d>\n"
1111                      "    <f/>\n"
1112                      "  </d>\n"
1113                      "</a>";
1114   const StructDataEntry expected[]
1115       = {{XCS("a"), 0, 1, STRUCT_START_TAG}, {XCS("b"), 2, 2, STRUCT_START_TAG},
1116          {XCS("c"), 4, 3, STRUCT_START_TAG}, {XCS("c"), 8, 3, STRUCT_END_TAG},
1117          {XCS("b"), 2, 4, STRUCT_END_TAG},   {XCS("d"), 2, 5, STRUCT_START_TAG},
1118          {XCS("f"), 4, 6, STRUCT_START_TAG}, {XCS("f"), 8, 6, STRUCT_END_TAG},
1119          {XCS("d"), 2, 7, STRUCT_END_TAG},   {XCS("a"), 0, 8, STRUCT_END_TAG}};
1120   const int expected_count = sizeof(expected) / sizeof(StructDataEntry);
1121   StructData storage;
1122 
1123   StructData_Init(&storage);
1124   XML_SetUserData(g_parser, &storage);
1125   XML_SetStartElementHandler(g_parser, start_element_event_handler2);
1126   XML_SetEndElementHandler(g_parser, end_element_event_handler2);
1127   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1128       == XML_STATUS_ERROR)
1129     xml_failure(g_parser);
1130 
1131   StructData_CheckItems(&storage, expected, expected_count);
1132   StructData_Dispose(&storage);
1133 }
1134 END_TEST
1135 
1136 /* Regression test #4 for SF bug #653180. */
START_TEST(test_line_number_after_error)1137 START_TEST(test_line_number_after_error) {
1138   const char *text = "<a>\n"
1139                      "  <b>\n"
1140                      "  </a>"; /* missing </b> */
1141   XML_Size lineno;
1142   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
1143       != XML_STATUS_ERROR)
1144     fail("Expected a parse error");
1145 
1146   lineno = XML_GetCurrentLineNumber(g_parser);
1147   if (lineno != 3) {
1148     char buffer[100];
1149     sprintf(buffer, "expected 3 lines, saw %" XML_FMT_INT_MOD "u", lineno);
1150     fail(buffer);
1151   }
1152 }
1153 END_TEST
1154 
1155 /* Regression test #5 for SF bug #653180. */
START_TEST(test_column_number_after_error)1156 START_TEST(test_column_number_after_error) {
1157   const char *text = "<a>\n"
1158                      "  <b>\n"
1159                      "  </a>"; /* missing </b> */
1160   XML_Size colno;
1161   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
1162       != XML_STATUS_ERROR)
1163     fail("Expected a parse error");
1164 
1165   colno = XML_GetCurrentColumnNumber(g_parser);
1166   if (colno != 4) {
1167     char buffer[100];
1168     sprintf(buffer, "expected 4 columns, saw %" XML_FMT_INT_MOD "u", colno);
1169     fail(buffer);
1170   }
1171 }
1172 END_TEST
1173 
1174 /* Regression test for SF bug #478332. */
START_TEST(test_really_long_lines)1175 START_TEST(test_really_long_lines) {
1176   /* This parses an input line longer than INIT_DATA_BUF_SIZE
1177      characters long (defined to be 1024 in xmlparse.c).  We take a
1178      really cheesy approach to building the input buffer, because
1179      this avoids writing bugs in buffer-filling code.
1180   */
1181   const char *text
1182       = "<e>"
1183         /* 64 chars */
1184         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1185         /* until we have at least 1024 characters on the line: */
1186         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1187         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1188         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1189         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1190         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1191         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1192         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1193         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1194         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1195         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1196         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1197         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1198         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1199         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1200         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1201         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1202         "</e>";
1203   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1204       == XML_STATUS_ERROR)
1205     xml_failure(g_parser);
1206 }
1207 END_TEST
1208 
1209 /* Test cdata processing across a buffer boundary */
START_TEST(test_really_long_encoded_lines)1210 START_TEST(test_really_long_encoded_lines) {
1211   /* As above, except that we want to provoke an output buffer
1212    * overflow with a non-trivial encoding.  For this we need to pass
1213    * the whole cdata in one go, not byte-by-byte.
1214    */
1215   void *buffer;
1216   const char *text
1217       = "<?xml version='1.0' encoding='iso-8859-1'?>"
1218         "<e>"
1219         /* 64 chars */
1220         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1221         /* until we have at least 1024 characters on the line: */
1222         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1223         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1224         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1225         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1226         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1227         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1228         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1229         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1230         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1231         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1232         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1233         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1234         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1235         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1236         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1237         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1238         "</e>";
1239   int parse_len = (int)strlen(text);
1240 
1241   /* Need a cdata handler to provoke the code path we want to test */
1242   XML_SetCharacterDataHandler(g_parser, dummy_cdata_handler);
1243   buffer = XML_GetBuffer(g_parser, parse_len);
1244   if (buffer == NULL)
1245     fail("Could not allocate parse buffer");
1246   assert(buffer != NULL);
1247   memcpy(buffer, text, parse_len);
1248   if (XML_ParseBuffer(g_parser, parse_len, XML_TRUE) == XML_STATUS_ERROR)
1249     xml_failure(g_parser);
1250 }
1251 END_TEST
1252 
1253 /*
1254  * Element event tests.
1255  */
1256 
1257 static void XMLCALL
start_element_event_handler(void * userData,const XML_Char * name,const XML_Char ** atts)1258 start_element_event_handler(void *userData, const XML_Char *name,
1259                             const XML_Char **atts) {
1260   UNUSED_P(atts);
1261   CharData_AppendXMLChars((CharData *)userData, name, -1);
1262 }
1263 
1264 static void XMLCALL
end_element_event_handler(void * userData,const XML_Char * name)1265 end_element_event_handler(void *userData, const XML_Char *name) {
1266   CharData *storage = (CharData *)userData;
1267   CharData_AppendXMLChars(storage, XCS("/"), 1);
1268   CharData_AppendXMLChars(storage, name, -1);
1269 }
1270 
START_TEST(test_end_element_events)1271 START_TEST(test_end_element_events) {
1272   const char *text = "<a><b><c/></b><d><f/></d></a>";
1273   const XML_Char *expected = XCS("/c/b/f/d/a");
1274   CharData storage;
1275 
1276   CharData_Init(&storage);
1277   XML_SetUserData(g_parser, &storage);
1278   XML_SetEndElementHandler(g_parser, end_element_event_handler);
1279   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1280       == XML_STATUS_ERROR)
1281     xml_failure(g_parser);
1282   CharData_CheckXMLChars(&storage, expected);
1283 }
1284 END_TEST
1285 
1286 /*
1287  * Attribute tests.
1288  */
1289 
1290 /* Helpers used by the following test; this checks any "attr" and "refs"
1291    attributes to make sure whitespace has been normalized.
1292 
1293    Return true if whitespace has been normalized in a string, using
1294    the rules for attribute value normalization.  The 'is_cdata' flag
1295    is needed since CDATA attributes don't need to have multiple
1296    whitespace characters collapsed to a single space, while other
1297    attribute data types do.  (Section 3.3.3 of the recommendation.)
1298 */
1299 static int
is_whitespace_normalized(const XML_Char * s,int is_cdata)1300 is_whitespace_normalized(const XML_Char *s, int is_cdata) {
1301   int blanks = 0;
1302   int at_start = 1;
1303   while (*s) {
1304     if (*s == XCS(' '))
1305       ++blanks;
1306     else if (*s == XCS('\t') || *s == XCS('\n') || *s == XCS('\r'))
1307       return 0;
1308     else {
1309       if (at_start) {
1310         at_start = 0;
1311         if (blanks && ! is_cdata)
1312           /* illegal leading blanks */
1313           return 0;
1314       } else if (blanks > 1 && ! is_cdata)
1315         return 0;
1316       blanks = 0;
1317     }
1318     ++s;
1319   }
1320   if (blanks && ! is_cdata)
1321     return 0;
1322   return 1;
1323 }
1324 
1325 /* Check the attribute whitespace checker: */
1326 static void
testhelper_is_whitespace_normalized(void)1327 testhelper_is_whitespace_normalized(void) {
1328   assert(is_whitespace_normalized(XCS("abc"), 0));
1329   assert(is_whitespace_normalized(XCS("abc"), 1));
1330   assert(is_whitespace_normalized(XCS("abc def ghi"), 0));
1331   assert(is_whitespace_normalized(XCS("abc def ghi"), 1));
1332   assert(! is_whitespace_normalized(XCS(" abc def ghi"), 0));
1333   assert(is_whitespace_normalized(XCS(" abc def ghi"), 1));
1334   assert(! is_whitespace_normalized(XCS("abc  def ghi"), 0));
1335   assert(is_whitespace_normalized(XCS("abc  def ghi"), 1));
1336   assert(! is_whitespace_normalized(XCS("abc def ghi "), 0));
1337   assert(is_whitespace_normalized(XCS("abc def ghi "), 1));
1338   assert(! is_whitespace_normalized(XCS(" "), 0));
1339   assert(is_whitespace_normalized(XCS(" "), 1));
1340   assert(! is_whitespace_normalized(XCS("\t"), 0));
1341   assert(! is_whitespace_normalized(XCS("\t"), 1));
1342   assert(! is_whitespace_normalized(XCS("\n"), 0));
1343   assert(! is_whitespace_normalized(XCS("\n"), 1));
1344   assert(! is_whitespace_normalized(XCS("\r"), 0));
1345   assert(! is_whitespace_normalized(XCS("\r"), 1));
1346   assert(! is_whitespace_normalized(XCS("abc\t def"), 1));
1347 }
1348 
1349 static void XMLCALL
check_attr_contains_normalized_whitespace(void * userData,const XML_Char * name,const XML_Char ** atts)1350 check_attr_contains_normalized_whitespace(void *userData, const XML_Char *name,
1351                                           const XML_Char **atts) {
1352   int i;
1353   UNUSED_P(userData);
1354   UNUSED_P(name);
1355   for (i = 0; atts[i] != NULL; i += 2) {
1356     const XML_Char *attrname = atts[i];
1357     const XML_Char *value = atts[i + 1];
1358     if (xcstrcmp(XCS("attr"), attrname) == 0
1359         || xcstrcmp(XCS("ents"), attrname) == 0
1360         || xcstrcmp(XCS("refs"), attrname) == 0) {
1361       if (! is_whitespace_normalized(value, 0)) {
1362         char buffer[256];
1363         sprintf(buffer,
1364                 "attribute value not normalized: %" XML_FMT_STR
1365                 "='%" XML_FMT_STR "'",
1366                 attrname, value);
1367         fail(buffer);
1368       }
1369     }
1370   }
1371 }
1372 
START_TEST(test_attr_whitespace_normalization)1373 START_TEST(test_attr_whitespace_normalization) {
1374   const char *text
1375       = "<!DOCTYPE doc [\n"
1376         "  <!ATTLIST doc\n"
1377         "            attr NMTOKENS #REQUIRED\n"
1378         "            ents ENTITIES #REQUIRED\n"
1379         "            refs IDREFS   #REQUIRED>\n"
1380         "]>\n"
1381         "<doc attr='    a  b c\t\td\te\t' refs=' id-1   \t  id-2\t\t'  \n"
1382         "     ents=' ent-1   \t\r\n"
1383         "            ent-2  ' >\n"
1384         "  <e id='id-1'/>\n"
1385         "  <e id='id-2'/>\n"
1386         "</doc>";
1387 
1388   XML_SetStartElementHandler(g_parser,
1389                              check_attr_contains_normalized_whitespace);
1390   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1391       == XML_STATUS_ERROR)
1392     xml_failure(g_parser);
1393 }
1394 END_TEST
1395 
1396 /*
1397  * XML declaration tests.
1398  */
1399 
START_TEST(test_xmldecl_misplaced)1400 START_TEST(test_xmldecl_misplaced) {
1401   expect_failure("\n"
1402                  "<?xml version='1.0'?>\n"
1403                  "<a/>",
1404                  XML_ERROR_MISPLACED_XML_PI,
1405                  "failed to report misplaced XML declaration");
1406 }
1407 END_TEST
1408 
START_TEST(test_xmldecl_invalid)1409 START_TEST(test_xmldecl_invalid) {
1410   expect_failure("<?xml version='1.0' \xc3\xa7?>\n<doc/>", XML_ERROR_XML_DECL,
1411                  "Failed to report invalid XML declaration");
1412 }
1413 END_TEST
1414 
START_TEST(test_xmldecl_missing_attr)1415 START_TEST(test_xmldecl_missing_attr) {
1416   expect_failure("<?xml ='1.0'?>\n<doc/>\n", XML_ERROR_XML_DECL,
1417                  "Failed to report missing XML declaration attribute");
1418 }
1419 END_TEST
1420 
START_TEST(test_xmldecl_missing_value)1421 START_TEST(test_xmldecl_missing_value) {
1422   expect_failure("<?xml version='1.0' encoding='us-ascii' standalone?>\n"
1423                  "<doc/>",
1424                  XML_ERROR_XML_DECL,
1425                  "Failed to report missing attribute value");
1426 }
1427 END_TEST
1428 
1429 /* Regression test for SF bug #584832. */
1430 static int XMLCALL
UnknownEncodingHandler(void * data,const XML_Char * encoding,XML_Encoding * info)1431 UnknownEncodingHandler(void *data, const XML_Char *encoding,
1432                        XML_Encoding *info) {
1433   UNUSED_P(data);
1434   if (xcstrcmp(encoding, XCS("unsupported-encoding")) == 0) {
1435     int i;
1436     for (i = 0; i < 256; ++i)
1437       info->map[i] = i;
1438     info->data = NULL;
1439     info->convert = NULL;
1440     info->release = NULL;
1441     return XML_STATUS_OK;
1442   }
1443   return XML_STATUS_ERROR;
1444 }
1445 
START_TEST(test_unknown_encoding_internal_entity)1446 START_TEST(test_unknown_encoding_internal_entity) {
1447   const char *text = "<?xml version='1.0' encoding='unsupported-encoding'?>\n"
1448                      "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n"
1449                      "<test a='&foo;'/>";
1450 
1451   XML_SetUnknownEncodingHandler(g_parser, UnknownEncodingHandler, NULL);
1452   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1453       == XML_STATUS_ERROR)
1454     xml_failure(g_parser);
1455 }
1456 END_TEST
1457 
1458 /* Test unrecognised encoding handler */
1459 static void
dummy_release(void * data)1460 dummy_release(void *data) {
1461   UNUSED_P(data);
1462 }
1463 
1464 static int XMLCALL
UnrecognisedEncodingHandler(void * data,const XML_Char * encoding,XML_Encoding * info)1465 UnrecognisedEncodingHandler(void *data, const XML_Char *encoding,
1466                             XML_Encoding *info) {
1467   UNUSED_P(data);
1468   UNUSED_P(encoding);
1469   info->data = NULL;
1470   info->convert = NULL;
1471   info->release = dummy_release;
1472   return XML_STATUS_ERROR;
1473 }
1474 
START_TEST(test_unrecognised_encoding_internal_entity)1475 START_TEST(test_unrecognised_encoding_internal_entity) {
1476   const char *text = "<?xml version='1.0' encoding='unsupported-encoding'?>\n"
1477                      "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n"
1478                      "<test a='&foo;'/>";
1479 
1480   XML_SetUnknownEncodingHandler(g_parser, UnrecognisedEncodingHandler, NULL);
1481   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1482       != XML_STATUS_ERROR)
1483     fail("Unrecognised encoding not rejected");
1484 }
1485 END_TEST
1486 
1487 /* Regression test for SF bug #620106. */
1488 static int XMLCALL
external_entity_loader(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)1489 external_entity_loader(XML_Parser parser, const XML_Char *context,
1490                        const XML_Char *base, const XML_Char *systemId,
1491                        const XML_Char *publicId) {
1492   ExtTest *test_data = (ExtTest *)XML_GetUserData(parser);
1493   XML_Parser extparser;
1494 
1495   UNUSED_P(base);
1496   UNUSED_P(systemId);
1497   UNUSED_P(publicId);
1498   extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
1499   if (extparser == NULL)
1500     fail("Could not create external entity parser.");
1501   if (test_data->encoding != NULL) {
1502     if (! XML_SetEncoding(extparser, test_data->encoding))
1503       fail("XML_SetEncoding() ignored for external entity");
1504   }
1505   if (_XML_Parse_SINGLE_BYTES(extparser, test_data->parse_text,
1506                               (int)strlen(test_data->parse_text), XML_TRUE)
1507       == XML_STATUS_ERROR) {
1508     xml_failure(extparser);
1509     return XML_STATUS_ERROR;
1510   }
1511   XML_ParserFree(extparser);
1512   return XML_STATUS_OK;
1513 }
1514 
START_TEST(test_ext_entity_set_encoding)1515 START_TEST(test_ext_entity_set_encoding) {
1516   const char *text = "<!DOCTYPE doc [\n"
1517                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1518                      "]>\n"
1519                      "<doc>&en;</doc>";
1520   ExtTest test_data
1521       = {/* This text says it's an unsupported encoding, but it's really
1522             UTF-8, which we tell Expat using XML_SetEncoding().
1523          */
1524          "<?xml encoding='iso-8859-3'?>\xC3\xA9", XCS("utf-8"), NULL};
1525 #ifdef XML_UNICODE
1526   const XML_Char *expected = XCS("\x00e9");
1527 #else
1528   const XML_Char *expected = XCS("\xc3\xa9");
1529 #endif
1530 
1531   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1532   run_ext_character_check(text, &test_data, expected);
1533 }
1534 END_TEST
1535 
1536 /* Test external entities with no handler */
START_TEST(test_ext_entity_no_handler)1537 START_TEST(test_ext_entity_no_handler) {
1538   const char *text = "<!DOCTYPE doc [\n"
1539                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1540                      "]>\n"
1541                      "<doc>&en;</doc>";
1542 
1543   XML_SetDefaultHandler(g_parser, dummy_default_handler);
1544   run_character_check(text, XCS(""));
1545 }
1546 END_TEST
1547 
1548 /* Test UTF-8 BOM is accepted */
START_TEST(test_ext_entity_set_bom)1549 START_TEST(test_ext_entity_set_bom) {
1550   const char *text = "<!DOCTYPE doc [\n"
1551                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1552                      "]>\n"
1553                      "<doc>&en;</doc>";
1554   ExtTest test_data = {"\xEF\xBB\xBF" /* BOM */
1555                        "<?xml encoding='iso-8859-3'?>"
1556                        "\xC3\xA9",
1557                        XCS("utf-8"), NULL};
1558 #ifdef XML_UNICODE
1559   const XML_Char *expected = XCS("\x00e9");
1560 #else
1561   const XML_Char *expected = XCS("\xc3\xa9");
1562 #endif
1563 
1564   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1565   run_ext_character_check(text, &test_data, expected);
1566 }
1567 END_TEST
1568 
1569 /* Test that bad encodings are faulted */
1570 typedef struct ext_faults {
1571   const char *parse_text;
1572   const char *fail_text;
1573   const XML_Char *encoding;
1574   enum XML_Error error;
1575 } ExtFaults;
1576 
1577 static int XMLCALL
external_entity_faulter(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)1578 external_entity_faulter(XML_Parser parser, const XML_Char *context,
1579                         const XML_Char *base, const XML_Char *systemId,
1580                         const XML_Char *publicId) {
1581   XML_Parser ext_parser;
1582   ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser);
1583 
1584   UNUSED_P(base);
1585   UNUSED_P(systemId);
1586   UNUSED_P(publicId);
1587   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
1588   if (ext_parser == NULL)
1589     fail("Could not create external entity parser");
1590   if (fault->encoding != NULL) {
1591     if (! XML_SetEncoding(ext_parser, fault->encoding))
1592       fail("XML_SetEncoding failed");
1593   }
1594   if (_XML_Parse_SINGLE_BYTES(ext_parser, fault->parse_text,
1595                               (int)strlen(fault->parse_text), XML_TRUE)
1596       != XML_STATUS_ERROR)
1597     fail(fault->fail_text);
1598   if (XML_GetErrorCode(ext_parser) != fault->error)
1599     xml_failure(ext_parser);
1600 
1601   XML_ParserFree(ext_parser);
1602   return XML_STATUS_ERROR;
1603 }
1604 
START_TEST(test_ext_entity_bad_encoding)1605 START_TEST(test_ext_entity_bad_encoding) {
1606   const char *text = "<!DOCTYPE doc [\n"
1607                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1608                      "]>\n"
1609                      "<doc>&en;</doc>";
1610   ExtFaults fault
1611       = {"<?xml encoding='iso-8859-3'?>u", "Unsupported encoding not faulted",
1612          XCS("unknown"), XML_ERROR_UNKNOWN_ENCODING};
1613 
1614   XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
1615   XML_SetUserData(g_parser, &fault);
1616   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
1617                  "Bad encoding should not have been accepted");
1618 }
1619 END_TEST
1620 
1621 /* Try handing an invalid encoding to an external entity parser */
START_TEST(test_ext_entity_bad_encoding_2)1622 START_TEST(test_ext_entity_bad_encoding_2) {
1623   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
1624                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
1625                      "<doc>&entity;</doc>";
1626   ExtFaults fault
1627       = {"<!ELEMENT doc (#PCDATA)*>", "Unknown encoding not faulted",
1628          XCS("unknown-encoding"), XML_ERROR_UNKNOWN_ENCODING};
1629 
1630   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1631   XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
1632   XML_SetUserData(g_parser, &fault);
1633   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
1634                  "Bad encoding not faulted in external entity handler");
1635 }
1636 END_TEST
1637 
1638 /* Test that no error is reported for unknown entities if we don't
1639    read an external subset.  This was fixed in Expat 1.95.5.
1640 */
START_TEST(test_wfc_undeclared_entity_unread_external_subset)1641 START_TEST(test_wfc_undeclared_entity_unread_external_subset) {
1642   const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
1643                      "<doc>&entity;</doc>";
1644 
1645   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1646       == XML_STATUS_ERROR)
1647     xml_failure(g_parser);
1648 }
1649 END_TEST
1650 
1651 /* Test that an error is reported for unknown entities if we don't
1652    have an external subset.
1653 */
START_TEST(test_wfc_undeclared_entity_no_external_subset)1654 START_TEST(test_wfc_undeclared_entity_no_external_subset) {
1655   expect_failure("<doc>&entity;</doc>", XML_ERROR_UNDEFINED_ENTITY,
1656                  "Parser did not report undefined entity w/out a DTD.");
1657 }
1658 END_TEST
1659 
1660 /* Test that an error is reported for unknown entities if we don't
1661    read an external subset, but have been declared standalone.
1662 */
START_TEST(test_wfc_undeclared_entity_standalone)1663 START_TEST(test_wfc_undeclared_entity_standalone) {
1664   const char *text
1665       = "<?xml version='1.0' encoding='us-ascii' standalone='yes'?>\n"
1666         "<!DOCTYPE doc SYSTEM 'foo'>\n"
1667         "<doc>&entity;</doc>";
1668 
1669   expect_failure(text, XML_ERROR_UNDEFINED_ENTITY,
1670                  "Parser did not report undefined entity (standalone).");
1671 }
1672 END_TEST
1673 
1674 /* Test that an error is reported for unknown entities if we have read
1675    an external subset, and standalone is true.
1676 */
START_TEST(test_wfc_undeclared_entity_with_external_subset_standalone)1677 START_TEST(test_wfc_undeclared_entity_with_external_subset_standalone) {
1678   const char *text
1679       = "<?xml version='1.0' encoding='us-ascii' standalone='yes'?>\n"
1680         "<!DOCTYPE doc SYSTEM 'foo'>\n"
1681         "<doc>&entity;</doc>";
1682   ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
1683 
1684   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1685   XML_SetUserData(g_parser, &test_data);
1686   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1687   expect_failure(text, XML_ERROR_UNDEFINED_ENTITY,
1688                  "Parser did not report undefined entity (external DTD).");
1689 }
1690 END_TEST
1691 
1692 /* Test that external entity handling is not done if the parsing flag
1693  * is set to UNLESS_STANDALONE
1694  */
START_TEST(test_entity_with_external_subset_unless_standalone)1695 START_TEST(test_entity_with_external_subset_unless_standalone) {
1696   const char *text
1697       = "<?xml version='1.0' encoding='us-ascii' standalone='yes'?>\n"
1698         "<!DOCTYPE doc SYSTEM 'foo'>\n"
1699         "<doc>&entity;</doc>";
1700   ExtTest test_data = {"<!ENTITY entity 'bar'>", NULL, NULL};
1701 
1702   XML_SetParamEntityParsing(g_parser,
1703                             XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE);
1704   XML_SetUserData(g_parser, &test_data);
1705   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1706   expect_failure(text, XML_ERROR_UNDEFINED_ENTITY,
1707                  "Parser did not report undefined entity");
1708 }
1709 END_TEST
1710 
1711 /* Test that no error is reported for unknown entities if we have read
1712    an external subset, and standalone is false.
1713 */
START_TEST(test_wfc_undeclared_entity_with_external_subset)1714 START_TEST(test_wfc_undeclared_entity_with_external_subset) {
1715   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
1716                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
1717                      "<doc>&entity;</doc>";
1718   ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
1719 
1720   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1721   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1722   run_ext_character_check(text, &test_data, XCS(""));
1723 }
1724 END_TEST
1725 
1726 /* Test that an error is reported if our NotStandalone handler fails */
1727 static int XMLCALL
reject_not_standalone_handler(void * userData)1728 reject_not_standalone_handler(void *userData) {
1729   UNUSED_P(userData);
1730   return XML_STATUS_ERROR;
1731 }
1732 
START_TEST(test_not_standalone_handler_reject)1733 START_TEST(test_not_standalone_handler_reject) {
1734   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
1735                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
1736                      "<doc>&entity;</doc>";
1737   ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
1738 
1739   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1740   XML_SetUserData(g_parser, &test_data);
1741   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1742   XML_SetNotStandaloneHandler(g_parser, reject_not_standalone_handler);
1743   expect_failure(text, XML_ERROR_NOT_STANDALONE,
1744                  "NotStandalone handler failed to reject");
1745 
1746   /* Try again but without external entity handling */
1747   XML_ParserReset(g_parser, NULL);
1748   XML_SetNotStandaloneHandler(g_parser, reject_not_standalone_handler);
1749   expect_failure(text, XML_ERROR_NOT_STANDALONE,
1750                  "NotStandalone handler failed to reject");
1751 }
1752 END_TEST
1753 
1754 /* Test that no error is reported if our NotStandalone handler succeeds */
1755 static int XMLCALL
accept_not_standalone_handler(void * userData)1756 accept_not_standalone_handler(void *userData) {
1757   UNUSED_P(userData);
1758   return XML_STATUS_OK;
1759 }
1760 
START_TEST(test_not_standalone_handler_accept)1761 START_TEST(test_not_standalone_handler_accept) {
1762   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
1763                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
1764                      "<doc>&entity;</doc>";
1765   ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
1766 
1767   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1768   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1769   XML_SetNotStandaloneHandler(g_parser, accept_not_standalone_handler);
1770   run_ext_character_check(text, &test_data, XCS(""));
1771 
1772   /* Repeat without the external entity handler */
1773   XML_ParserReset(g_parser, NULL);
1774   XML_SetNotStandaloneHandler(g_parser, accept_not_standalone_handler);
1775   run_character_check(text, XCS(""));
1776 }
1777 END_TEST
1778 
START_TEST(test_wfc_no_recursive_entity_refs)1779 START_TEST(test_wfc_no_recursive_entity_refs) {
1780   const char *text = "<!DOCTYPE doc [\n"
1781                      "  <!ENTITY entity '&#38;entity;'>\n"
1782                      "]>\n"
1783                      "<doc>&entity;</doc>";
1784 
1785   expect_failure(text, XML_ERROR_RECURSIVE_ENTITY_REF,
1786                  "Parser did not report recursive entity reference.");
1787 }
1788 END_TEST
1789 
1790 /* Test incomplete external entities are faulted */
START_TEST(test_ext_entity_invalid_parse)1791 START_TEST(test_ext_entity_invalid_parse) {
1792   const char *text = "<!DOCTYPE doc [\n"
1793                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1794                      "]>\n"
1795                      "<doc>&en;</doc>";
1796   const ExtFaults faults[]
1797       = {{"<", "Incomplete element declaration not faulted", NULL,
1798           XML_ERROR_UNCLOSED_TOKEN},
1799          {"<\xe2\x82", /* First two bytes of a three-byte char */
1800           "Incomplete character not faulted", NULL, XML_ERROR_PARTIAL_CHAR},
1801          {"<tag>\xe2\x82", "Incomplete character in CDATA not faulted", NULL,
1802           XML_ERROR_PARTIAL_CHAR},
1803          {NULL, NULL, NULL, XML_ERROR_NONE}};
1804   const ExtFaults *fault = faults;
1805 
1806   for (; fault->parse_text != NULL; fault++) {
1807     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1808     XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
1809     XML_SetUserData(g_parser, (void *)fault);
1810     expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
1811                    "Parser did not report external entity error");
1812     XML_ParserReset(g_parser, NULL);
1813   }
1814 }
1815 END_TEST
1816 
1817 /* Regression test for SF bug #483514. */
START_TEST(test_dtd_default_handling)1818 START_TEST(test_dtd_default_handling) {
1819   const char *text = "<!DOCTYPE doc [\n"
1820                      "<!ENTITY e SYSTEM 'http://example.org/e'>\n"
1821                      "<!NOTATION n SYSTEM 'http://example.org/n'>\n"
1822                      "<!ELEMENT doc EMPTY>\n"
1823                      "<!ATTLIST doc a CDATA #IMPLIED>\n"
1824                      "<?pi in dtd?>\n"
1825                      "<!--comment in dtd-->\n"
1826                      "]><doc/>";
1827 
1828   XML_SetDefaultHandler(g_parser, accumulate_characters);
1829   XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler);
1830   XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler);
1831   XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
1832   XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
1833   XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
1834   XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
1835   XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
1836   XML_SetCommentHandler(g_parser, dummy_comment_handler);
1837   XML_SetStartCdataSectionHandler(g_parser, dummy_start_cdata_handler);
1838   XML_SetEndCdataSectionHandler(g_parser, dummy_end_cdata_handler);
1839   run_character_check(text, XCS("\n\n\n\n\n\n\n<doc/>"));
1840 }
1841 END_TEST
1842 
1843 /* Test handling of attribute declarations */
1844 typedef struct AttTest {
1845   const char *definition;
1846   const XML_Char *element_name;
1847   const XML_Char *attr_name;
1848   const XML_Char *attr_type;
1849   const XML_Char *default_value;
1850   int is_required;
1851 } AttTest;
1852 
1853 static void XMLCALL
verify_attlist_decl_handler(void * userData,const XML_Char * element_name,const XML_Char * attr_name,const XML_Char * attr_type,const XML_Char * default_value,int is_required)1854 verify_attlist_decl_handler(void *userData, const XML_Char *element_name,
1855                             const XML_Char *attr_name,
1856                             const XML_Char *attr_type,
1857                             const XML_Char *default_value, int is_required) {
1858   AttTest *at = (AttTest *)userData;
1859 
1860   if (xcstrcmp(element_name, at->element_name))
1861     fail("Unexpected element name in attribute declaration");
1862   if (xcstrcmp(attr_name, at->attr_name))
1863     fail("Unexpected attribute name in attribute declaration");
1864   if (xcstrcmp(attr_type, at->attr_type))
1865     fail("Unexpected attribute type in attribute declaration");
1866   if ((default_value == NULL && at->default_value != NULL)
1867       || (default_value != NULL && at->default_value == NULL)
1868       || (default_value != NULL && xcstrcmp(default_value, at->default_value)))
1869     fail("Unexpected default value in attribute declaration");
1870   if (is_required != at->is_required)
1871     fail("Requirement mismatch in attribute declaration");
1872 }
1873 
START_TEST(test_dtd_attr_handling)1874 START_TEST(test_dtd_attr_handling) {
1875   const char *prolog = "<!DOCTYPE doc [\n"
1876                        "<!ELEMENT doc EMPTY>\n";
1877   AttTest attr_data[]
1878       = {{"<!ATTLIST doc a ( one | two | three ) #REQUIRED>\n"
1879           "]>"
1880           "<doc a='two'/>",
1881           XCS("doc"), XCS("a"),
1882           XCS("(one|two|three)"), /* Extraneous spaces will be removed */
1883           NULL, XML_TRUE},
1884          {"<!NOTATION foo SYSTEM 'http://example.org/foo'>\n"
1885           "<!ATTLIST doc a NOTATION (foo) #IMPLIED>\n"
1886           "]>"
1887           "<doc/>",
1888           XCS("doc"), XCS("a"), XCS("NOTATION(foo)"), NULL, XML_FALSE},
1889          {"<!ATTLIST doc a NOTATION (foo) 'bar'>\n"
1890           "]>"
1891           "<doc/>",
1892           XCS("doc"), XCS("a"), XCS("NOTATION(foo)"), XCS("bar"), XML_FALSE},
1893          {"<!ATTLIST doc a CDATA '\xdb\xb2'>\n"
1894           "]>"
1895           "<doc/>",
1896           XCS("doc"), XCS("a"), XCS("CDATA"),
1897 #ifdef XML_UNICODE
1898           XCS("\x06f2"),
1899 #else
1900           XCS("\xdb\xb2"),
1901 #endif
1902           XML_FALSE},
1903          {NULL, NULL, NULL, NULL, NULL, XML_FALSE}};
1904   AttTest *test;
1905 
1906   for (test = attr_data; test->definition != NULL; test++) {
1907     XML_SetAttlistDeclHandler(g_parser, verify_attlist_decl_handler);
1908     XML_SetUserData(g_parser, test);
1909     if (_XML_Parse_SINGLE_BYTES(g_parser, prolog, (int)strlen(prolog),
1910                                 XML_FALSE)
1911         == XML_STATUS_ERROR)
1912       xml_failure(g_parser);
1913     if (_XML_Parse_SINGLE_BYTES(g_parser, test->definition,
1914                                 (int)strlen(test->definition), XML_TRUE)
1915         == XML_STATUS_ERROR)
1916       xml_failure(g_parser);
1917     XML_ParserReset(g_parser, NULL);
1918   }
1919 }
1920 END_TEST
1921 
1922 /* See related SF bug #673791.
1923    When namespace processing is enabled, setting the namespace URI for
1924    a prefix is not allowed; this test ensures that it *is* allowed
1925    when namespace processing is not enabled.
1926    (See Namespaces in XML, section 2.)
1927 */
START_TEST(test_empty_ns_without_namespaces)1928 START_TEST(test_empty_ns_without_namespaces) {
1929   const char *text = "<doc xmlns:prefix='http://example.org/'>\n"
1930                      "  <e xmlns:prefix=''/>\n"
1931                      "</doc>";
1932 
1933   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1934       == XML_STATUS_ERROR)
1935     xml_failure(g_parser);
1936 }
1937 END_TEST
1938 
1939 /* Regression test for SF bug #824420.
1940    Checks that an xmlns:prefix attribute set in an attribute's default
1941    value isn't misinterpreted.
1942 */
START_TEST(test_ns_in_attribute_default_without_namespaces)1943 START_TEST(test_ns_in_attribute_default_without_namespaces) {
1944   const char *text = "<!DOCTYPE e:element [\n"
1945                      "  <!ATTLIST e:element\n"
1946                      "    xmlns:e CDATA 'http://example.org/'>\n"
1947                      "      ]>\n"
1948                      "<e:element/>";
1949 
1950   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1951       == XML_STATUS_ERROR)
1952     xml_failure(g_parser);
1953 }
1954 END_TEST
1955 
1956 static const char *long_character_data_text
1957     = "<?xml version='1.0' encoding='iso-8859-1'?><s>"
1958       "012345678901234567890123456789012345678901234567890123456789"
1959       "012345678901234567890123456789012345678901234567890123456789"
1960       "012345678901234567890123456789012345678901234567890123456789"
1961       "012345678901234567890123456789012345678901234567890123456789"
1962       "012345678901234567890123456789012345678901234567890123456789"
1963       "012345678901234567890123456789012345678901234567890123456789"
1964       "012345678901234567890123456789012345678901234567890123456789"
1965       "012345678901234567890123456789012345678901234567890123456789"
1966       "012345678901234567890123456789012345678901234567890123456789"
1967       "012345678901234567890123456789012345678901234567890123456789"
1968       "012345678901234567890123456789012345678901234567890123456789"
1969       "012345678901234567890123456789012345678901234567890123456789"
1970       "012345678901234567890123456789012345678901234567890123456789"
1971       "012345678901234567890123456789012345678901234567890123456789"
1972       "012345678901234567890123456789012345678901234567890123456789"
1973       "012345678901234567890123456789012345678901234567890123456789"
1974       "012345678901234567890123456789012345678901234567890123456789"
1975       "012345678901234567890123456789012345678901234567890123456789"
1976       "012345678901234567890123456789012345678901234567890123456789"
1977       "012345678901234567890123456789012345678901234567890123456789"
1978       "</s>";
1979 
1980 static XML_Bool resumable = XML_FALSE;
1981 
1982 static void
clearing_aborting_character_handler(void * userData,const XML_Char * s,int len)1983 clearing_aborting_character_handler(void *userData, const XML_Char *s,
1984                                     int len) {
1985   UNUSED_P(userData);
1986   UNUSED_P(s);
1987   UNUSED_P(len);
1988   XML_StopParser(g_parser, resumable);
1989   XML_SetCharacterDataHandler(g_parser, NULL);
1990 }
1991 
1992 /* Regression test for SF bug #1515266: missing check of stopped
1993    parser in doContext() 'for' loop. */
START_TEST(test_stop_parser_between_char_data_calls)1994 START_TEST(test_stop_parser_between_char_data_calls) {
1995   /* The sample data must be big enough that there are two calls to
1996      the character data handler from within the inner "for" loop of
1997      the XML_TOK_DATA_CHARS case in doContent(), and the character
1998      handler must stop the parser and clear the character data
1999      handler.
2000   */
2001   const char *text = long_character_data_text;
2002 
2003   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2004   resumable = XML_FALSE;
2005   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2006       != XML_STATUS_ERROR)
2007     xml_failure(g_parser);
2008   if (XML_GetErrorCode(g_parser) != XML_ERROR_ABORTED)
2009     xml_failure(g_parser);
2010 }
2011 END_TEST
2012 
2013 /* Regression test for SF bug #1515266: missing check of stopped
2014    parser in doContext() 'for' loop. */
START_TEST(test_suspend_parser_between_char_data_calls)2015 START_TEST(test_suspend_parser_between_char_data_calls) {
2016   /* The sample data must be big enough that there are two calls to
2017      the character data handler from within the inner "for" loop of
2018      the XML_TOK_DATA_CHARS case in doContent(), and the character
2019      handler must stop the parser and clear the character data
2020      handler.
2021   */
2022   const char *text = long_character_data_text;
2023 
2024   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2025   resumable = XML_TRUE;
2026   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2027       != XML_STATUS_SUSPENDED)
2028     xml_failure(g_parser);
2029   if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE)
2030     xml_failure(g_parser);
2031   /* Try parsing directly */
2032   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
2033       != XML_STATUS_ERROR)
2034     fail("Attempt to continue parse while suspended not faulted");
2035   if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED)
2036     fail("Suspended parse not faulted with correct error");
2037 }
2038 END_TEST
2039 
2040 static XML_Bool abortable = XML_FALSE;
2041 
2042 static void
parser_stop_character_handler(void * userData,const XML_Char * s,int len)2043 parser_stop_character_handler(void *userData, const XML_Char *s, int len) {
2044   UNUSED_P(userData);
2045   UNUSED_P(s);
2046   UNUSED_P(len);
2047   XML_StopParser(g_parser, resumable);
2048   XML_SetCharacterDataHandler(g_parser, NULL);
2049   if (! resumable) {
2050     /* Check that aborting an aborted parser is faulted */
2051     if (XML_StopParser(g_parser, XML_FALSE) != XML_STATUS_ERROR)
2052       fail("Aborting aborted parser not faulted");
2053     if (XML_GetErrorCode(g_parser) != XML_ERROR_FINISHED)
2054       xml_failure(g_parser);
2055   } else if (abortable) {
2056     /* Check that aborting a suspended parser works */
2057     if (XML_StopParser(g_parser, XML_FALSE) == XML_STATUS_ERROR)
2058       xml_failure(g_parser);
2059   } else {
2060     /* Check that suspending a suspended parser works */
2061     if (XML_StopParser(g_parser, XML_TRUE) != XML_STATUS_ERROR)
2062       fail("Suspending suspended parser not faulted");
2063     if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED)
2064       xml_failure(g_parser);
2065   }
2066 }
2067 
2068 /* Test repeated calls to XML_StopParser are handled correctly */
START_TEST(test_repeated_stop_parser_between_char_data_calls)2069 START_TEST(test_repeated_stop_parser_between_char_data_calls) {
2070   const char *text = long_character_data_text;
2071 
2072   XML_SetCharacterDataHandler(g_parser, parser_stop_character_handler);
2073   resumable = XML_FALSE;
2074   abortable = XML_FALSE;
2075   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2076       != XML_STATUS_ERROR)
2077     fail("Failed to double-stop parser");
2078 
2079   XML_ParserReset(g_parser, NULL);
2080   XML_SetCharacterDataHandler(g_parser, parser_stop_character_handler);
2081   resumable = XML_TRUE;
2082   abortable = XML_FALSE;
2083   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2084       != XML_STATUS_SUSPENDED)
2085     fail("Failed to double-suspend parser");
2086 
2087   XML_ParserReset(g_parser, NULL);
2088   XML_SetCharacterDataHandler(g_parser, parser_stop_character_handler);
2089   resumable = XML_TRUE;
2090   abortable = XML_TRUE;
2091   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2092       != XML_STATUS_ERROR)
2093     fail("Failed to suspend-abort parser");
2094 }
2095 END_TEST
2096 
START_TEST(test_good_cdata_ascii)2097 START_TEST(test_good_cdata_ascii) {
2098   const char *text = "<a><![CDATA[<greeting>Hello, world!</greeting>]]></a>";
2099   const XML_Char *expected = XCS("<greeting>Hello, world!</greeting>");
2100 
2101   CharData storage;
2102   CharData_Init(&storage);
2103   XML_SetUserData(g_parser, &storage);
2104   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2105   /* Add start and end handlers for coverage */
2106   XML_SetStartCdataSectionHandler(g_parser, dummy_start_cdata_handler);
2107   XML_SetEndCdataSectionHandler(g_parser, dummy_end_cdata_handler);
2108 
2109   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2110       == XML_STATUS_ERROR)
2111     xml_failure(g_parser);
2112   CharData_CheckXMLChars(&storage, expected);
2113 
2114   /* Try again, this time with a default handler */
2115   XML_ParserReset(g_parser, NULL);
2116   CharData_Init(&storage);
2117   XML_SetUserData(g_parser, &storage);
2118   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2119   XML_SetDefaultHandler(g_parser, dummy_default_handler);
2120 
2121   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2122       == XML_STATUS_ERROR)
2123     xml_failure(g_parser);
2124   CharData_CheckXMLChars(&storage, expected);
2125 }
2126 END_TEST
2127 
START_TEST(test_good_cdata_utf16)2128 START_TEST(test_good_cdata_utf16) {
2129   /* Test data is:
2130    *   <?xml version='1.0' encoding='utf-16'?>
2131    *   <a><![CDATA[hello]]></a>
2132    */
2133   const char text[]
2134       = "\0<\0?\0x\0m\0l\0"
2135         " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2136         " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0"
2137         "1\0"
2138         "6\0'"
2139         "\0?\0>\0\n"
2140         "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0[\0h\0e\0l\0l\0o\0]\0]\0>\0<\0/\0a\0>";
2141   const XML_Char *expected = XCS("hello");
2142 
2143   CharData storage;
2144   CharData_Init(&storage);
2145   XML_SetUserData(g_parser, &storage);
2146   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2147 
2148   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
2149       == XML_STATUS_ERROR)
2150     xml_failure(g_parser);
2151   CharData_CheckXMLChars(&storage, expected);
2152 }
2153 END_TEST
2154 
START_TEST(test_good_cdata_utf16_le)2155 START_TEST(test_good_cdata_utf16_le) {
2156   /* Test data is:
2157    *   <?xml version='1.0' encoding='utf-16'?>
2158    *   <a><![CDATA[hello]]></a>
2159    */
2160   const char text[]
2161       = "<\0?\0x\0m\0l\0"
2162         " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2163         " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0"
2164         "1\0"
2165         "6\0'"
2166         "\0?\0>\0\n"
2167         "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0[\0h\0e\0l\0l\0o\0]\0]\0>\0<\0/\0a\0>\0";
2168   const XML_Char *expected = XCS("hello");
2169 
2170   CharData storage;
2171   CharData_Init(&storage);
2172   XML_SetUserData(g_parser, &storage);
2173   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2174 
2175   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
2176       == XML_STATUS_ERROR)
2177     xml_failure(g_parser);
2178   CharData_CheckXMLChars(&storage, expected);
2179 }
2180 END_TEST
2181 
2182 /* Test UTF16 conversion of a long cdata string */
2183 
2184 /* 16 characters: handy macro to reduce visual clutter */
2185 #define A_TO_P_IN_UTF16 "\0A\0B\0C\0D\0E\0F\0G\0H\0I\0J\0K\0L\0M\0N\0O\0P"
2186 
START_TEST(test_long_cdata_utf16)2187 START_TEST(test_long_cdata_utf16) {
2188   /* Test data is:
2189    * <?xlm version='1.0' encoding='utf-16'?>
2190    * <a><![CDATA[
2191    * ABCDEFGHIJKLMNOP
2192    * ]]></a>
2193    */
2194   const char text[]
2195       = "\0<\0?\0x\0m\0l\0 "
2196         "\0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0 "
2197         "\0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0\x31\0\x36\0'\0?\0>"
2198         "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0["
2199       /* 64 characters per line */
2200       /* clang-format off */
2201         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2202         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2203         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2204         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2205         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2206         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2207         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2208         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2209         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2210         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2211         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2212         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2213         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2214         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2215         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2216         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2217         A_TO_P_IN_UTF16
2218         /* clang-format on */
2219         "\0]\0]\0>\0<\0/\0a\0>";
2220   const XML_Char *expected =
2221       /* clang-format off */
2222         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2223         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2224         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2225         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2226         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2227         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2228         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2229         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2230         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2231         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2232         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2233         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2234         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2235         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2236         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2237         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2238         XCS("ABCDEFGHIJKLMNOP");
2239   /* clang-format on */
2240   CharData storage;
2241   void *buffer;
2242 
2243   CharData_Init(&storage);
2244   XML_SetUserData(g_parser, &storage);
2245   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2246   buffer = XML_GetBuffer(g_parser, sizeof(text) - 1);
2247   if (buffer == NULL)
2248     fail("Could not allocate parse buffer");
2249   assert(buffer != NULL);
2250   memcpy(buffer, text, sizeof(text) - 1);
2251   if (XML_ParseBuffer(g_parser, sizeof(text) - 1, XML_TRUE) == XML_STATUS_ERROR)
2252     xml_failure(g_parser);
2253   CharData_CheckXMLChars(&storage, expected);
2254 }
2255 END_TEST
2256 
2257 /* Test handling of multiple unit UTF-16 characters */
START_TEST(test_multichar_cdata_utf16)2258 START_TEST(test_multichar_cdata_utf16) {
2259   /* Test data is:
2260    *   <?xml version='1.0' encoding='utf-16'?>
2261    *   <a><![CDATA[{MINIM}{CROTCHET}]]></a>
2262    *
2263    * where {MINIM} is U+1d15e (a minim or half-note)
2264    *   UTF-16: 0xd834 0xdd5e
2265    *   UTF-8:  0xf0 0x9d 0x85 0x9e
2266    * and {CROTCHET} is U+1d15f (a crotchet or quarter-note)
2267    *   UTF-16: 0xd834 0xdd5f
2268    *   UTF-8:  0xf0 0x9d 0x85 0x9f
2269    */
2270   const char text[] = "\0<\0?\0x\0m\0l\0"
2271                       " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2272                       " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0"
2273                       "1\0"
2274                       "6\0'"
2275                       "\0?\0>\0\n"
2276                       "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0["
2277                       "\xd8\x34\xdd\x5e\xd8\x34\xdd\x5f"
2278                       "\0]\0]\0>\0<\0/\0a\0>";
2279 #ifdef XML_UNICODE
2280   const XML_Char *expected = XCS("\xd834\xdd5e\xd834\xdd5f");
2281 #else
2282   const XML_Char *expected = XCS("\xf0\x9d\x85\x9e\xf0\x9d\x85\x9f");
2283 #endif
2284   CharData storage;
2285 
2286   CharData_Init(&storage);
2287   XML_SetUserData(g_parser, &storage);
2288   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2289 
2290   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
2291       == XML_STATUS_ERROR)
2292     xml_failure(g_parser);
2293   CharData_CheckXMLChars(&storage, expected);
2294 }
2295 END_TEST
2296 
2297 /* Test that an element name with a UTF-16 surrogate pair is rejected */
START_TEST(test_utf16_bad_surrogate_pair)2298 START_TEST(test_utf16_bad_surrogate_pair) {
2299   /* Test data is:
2300    *   <?xml version='1.0' encoding='utf-16'?>
2301    *   <a><![CDATA[{BADLINB}]]></a>
2302    *
2303    * where {BADLINB} is U+10000 (the first Linear B character)
2304    * with the UTF-16 surrogate pair in the wrong order, i.e.
2305    *   0xdc00 0xd800
2306    */
2307   const char text[] = "\0<\0?\0x\0m\0l\0"
2308                       " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2309                       " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0"
2310                       "1\0"
2311                       "6\0'"
2312                       "\0?\0>\0\n"
2313                       "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0["
2314                       "\xdc\x00\xd8\x00"
2315                       "\0]\0]\0>\0<\0/\0a\0>";
2316 
2317   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
2318       != XML_STATUS_ERROR)
2319     fail("Reversed UTF-16 surrogate pair not faulted");
2320   if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
2321     xml_failure(g_parser);
2322 }
2323 END_TEST
2324 
START_TEST(test_bad_cdata)2325 START_TEST(test_bad_cdata) {
2326   struct CaseData {
2327     const char *text;
2328     enum XML_Error expectedError;
2329   };
2330 
2331   struct CaseData cases[]
2332       = {{"<a><", XML_ERROR_UNCLOSED_TOKEN},
2333          {"<a><!", XML_ERROR_UNCLOSED_TOKEN},
2334          {"<a><![", XML_ERROR_UNCLOSED_TOKEN},
2335          {"<a><![C", XML_ERROR_UNCLOSED_TOKEN},
2336          {"<a><![CD", XML_ERROR_UNCLOSED_TOKEN},
2337          {"<a><![CDA", XML_ERROR_UNCLOSED_TOKEN},
2338          {"<a><![CDAT", XML_ERROR_UNCLOSED_TOKEN},
2339          {"<a><![CDATA", XML_ERROR_UNCLOSED_TOKEN},
2340 
2341          {"<a><![CDATA[", XML_ERROR_UNCLOSED_CDATA_SECTION},
2342          {"<a><![CDATA[]", XML_ERROR_UNCLOSED_CDATA_SECTION},
2343          {"<a><![CDATA[]]", XML_ERROR_UNCLOSED_CDATA_SECTION},
2344 
2345          {"<a><!<a/>", XML_ERROR_INVALID_TOKEN},
2346          {"<a><![<a/>", XML_ERROR_UNCLOSED_TOKEN},  /* ?! */
2347          {"<a><![C<a/>", XML_ERROR_UNCLOSED_TOKEN}, /* ?! */
2348          {"<a><![CD<a/>", XML_ERROR_INVALID_TOKEN},
2349          {"<a><![CDA<a/>", XML_ERROR_INVALID_TOKEN},
2350          {"<a><![CDAT<a/>", XML_ERROR_INVALID_TOKEN},
2351          {"<a><![CDATA<a/>", XML_ERROR_INVALID_TOKEN},
2352 
2353          {"<a><![CDATA[<a/>", XML_ERROR_UNCLOSED_CDATA_SECTION},
2354          {"<a><![CDATA[]<a/>", XML_ERROR_UNCLOSED_CDATA_SECTION},
2355          {"<a><![CDATA[]]<a/>", XML_ERROR_UNCLOSED_CDATA_SECTION}};
2356 
2357   size_t i = 0;
2358   for (; i < sizeof(cases) / sizeof(struct CaseData); i++) {
2359     const enum XML_Status actualStatus = _XML_Parse_SINGLE_BYTES(
2360         g_parser, cases[i].text, (int)strlen(cases[i].text), XML_TRUE);
2361     const enum XML_Error actualError = XML_GetErrorCode(g_parser);
2362 
2363     assert(actualStatus == XML_STATUS_ERROR);
2364 
2365     if (actualError != cases[i].expectedError) {
2366       char message[100];
2367       sprintf(message,
2368               "Expected error %d but got error %d for case %u: \"%s\"\n",
2369               cases[i].expectedError, actualError, (unsigned int)i + 1,
2370               cases[i].text);
2371       fail(message);
2372     }
2373 
2374     XML_ParserReset(g_parser, NULL);
2375   }
2376 }
2377 END_TEST
2378 
2379 /* Test failures in UTF-16 CDATA */
START_TEST(test_bad_cdata_utf16)2380 START_TEST(test_bad_cdata_utf16) {
2381   struct CaseData {
2382     size_t text_bytes;
2383     const char *text;
2384     enum XML_Error expected_error;
2385   };
2386 
2387   const char prolog[] = "\0<\0?\0x\0m\0l\0"
2388                         " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2389                         " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0"
2390                         "1\0"
2391                         "6\0'"
2392                         "\0?\0>\0\n"
2393                         "\0<\0a\0>";
2394   struct CaseData cases[] = {
2395       {1, "\0", XML_ERROR_UNCLOSED_TOKEN},
2396       {2, "\0<", XML_ERROR_UNCLOSED_TOKEN},
2397       {3, "\0<\0", XML_ERROR_UNCLOSED_TOKEN},
2398       {4, "\0<\0!", XML_ERROR_UNCLOSED_TOKEN},
2399       {5, "\0<\0!\0", XML_ERROR_UNCLOSED_TOKEN},
2400       {6, "\0<\0!\0[", XML_ERROR_UNCLOSED_TOKEN},
2401       {7, "\0<\0!\0[\0", XML_ERROR_UNCLOSED_TOKEN},
2402       {8, "\0<\0!\0[\0C", XML_ERROR_UNCLOSED_TOKEN},
2403       {9, "\0<\0!\0[\0C\0", XML_ERROR_UNCLOSED_TOKEN},
2404       {10, "\0<\0!\0[\0C\0D", XML_ERROR_UNCLOSED_TOKEN},
2405       {11, "\0<\0!\0[\0C\0D\0", XML_ERROR_UNCLOSED_TOKEN},
2406       {12, "\0<\0!\0[\0C\0D\0A", XML_ERROR_UNCLOSED_TOKEN},
2407       {13, "\0<\0!\0[\0C\0D\0A\0", XML_ERROR_UNCLOSED_TOKEN},
2408       {14, "\0<\0!\0[\0C\0D\0A\0T", XML_ERROR_UNCLOSED_TOKEN},
2409       {15, "\0<\0!\0[\0C\0D\0A\0T\0", XML_ERROR_UNCLOSED_TOKEN},
2410       {16, "\0<\0!\0[\0C\0D\0A\0T\0A", XML_ERROR_UNCLOSED_TOKEN},
2411       {17, "\0<\0!\0[\0C\0D\0A\0T\0A\0", XML_ERROR_UNCLOSED_TOKEN},
2412       {18, "\0<\0!\0[\0C\0D\0A\0T\0A\0[", XML_ERROR_UNCLOSED_CDATA_SECTION},
2413       {19, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0", XML_ERROR_UNCLOSED_CDATA_SECTION},
2414       {20, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z", XML_ERROR_UNCLOSED_CDATA_SECTION},
2415       /* Now add a four-byte UTF-16 character */
2416       {21, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8",
2417        XML_ERROR_UNCLOSED_CDATA_SECTION},
2418       {22, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8\x34", XML_ERROR_PARTIAL_CHAR},
2419       {23, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8\x34\xdd",
2420        XML_ERROR_PARTIAL_CHAR},
2421       {24, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8\x34\xdd\x5e",
2422        XML_ERROR_UNCLOSED_CDATA_SECTION}};
2423   size_t i;
2424 
2425   for (i = 0; i < sizeof(cases) / sizeof(struct CaseData); i++) {
2426     enum XML_Status actual_status;
2427     enum XML_Error actual_error;
2428 
2429     if (_XML_Parse_SINGLE_BYTES(g_parser, prolog, (int)sizeof(prolog) - 1,
2430                                 XML_FALSE)
2431         == XML_STATUS_ERROR)
2432       xml_failure(g_parser);
2433     actual_status = _XML_Parse_SINGLE_BYTES(g_parser, cases[i].text,
2434                                             (int)cases[i].text_bytes, XML_TRUE);
2435     assert(actual_status == XML_STATUS_ERROR);
2436     actual_error = XML_GetErrorCode(g_parser);
2437     if (actual_error != cases[i].expected_error) {
2438       char message[1024];
2439 
2440       sprintf(message,
2441               "Expected error %d (%" XML_FMT_STR "), got %d (%" XML_FMT_STR
2442               ") for case %lu\n",
2443               cases[i].expected_error, XML_ErrorString(cases[i].expected_error),
2444               actual_error, XML_ErrorString(actual_error),
2445               (long unsigned)(i + 1));
2446       fail(message);
2447     }
2448     XML_ParserReset(g_parser, NULL);
2449   }
2450 }
2451 END_TEST
2452 
2453 static const char *long_cdata_text
2454     = "<s><![CDATA["
2455       "012345678901234567890123456789012345678901234567890123456789"
2456       "012345678901234567890123456789012345678901234567890123456789"
2457       "012345678901234567890123456789012345678901234567890123456789"
2458       "012345678901234567890123456789012345678901234567890123456789"
2459       "012345678901234567890123456789012345678901234567890123456789"
2460       "012345678901234567890123456789012345678901234567890123456789"
2461       "012345678901234567890123456789012345678901234567890123456789"
2462       "012345678901234567890123456789012345678901234567890123456789"
2463       "012345678901234567890123456789012345678901234567890123456789"
2464       "012345678901234567890123456789012345678901234567890123456789"
2465       "012345678901234567890123456789012345678901234567890123456789"
2466       "012345678901234567890123456789012345678901234567890123456789"
2467       "012345678901234567890123456789012345678901234567890123456789"
2468       "012345678901234567890123456789012345678901234567890123456789"
2469       "012345678901234567890123456789012345678901234567890123456789"
2470       "012345678901234567890123456789012345678901234567890123456789"
2471       "012345678901234567890123456789012345678901234567890123456789"
2472       "012345678901234567890123456789012345678901234567890123456789"
2473       "012345678901234567890123456789012345678901234567890123456789"
2474       "012345678901234567890123456789012345678901234567890123456789"
2475       "]]></s>";
2476 
2477 /* Test stopping the parser in cdata handler */
START_TEST(test_stop_parser_between_cdata_calls)2478 START_TEST(test_stop_parser_between_cdata_calls) {
2479   const char *text = long_cdata_text;
2480 
2481   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2482   resumable = XML_FALSE;
2483   expect_failure(text, XML_ERROR_ABORTED, "Parse not aborted in CDATA handler");
2484 }
2485 END_TEST
2486 
2487 /* Test suspending the parser in cdata handler */
START_TEST(test_suspend_parser_between_cdata_calls)2488 START_TEST(test_suspend_parser_between_cdata_calls) {
2489   const char *text = long_cdata_text;
2490   enum XML_Status result;
2491 
2492   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2493   resumable = XML_TRUE;
2494   result = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE);
2495   if (result != XML_STATUS_SUSPENDED) {
2496     if (result == XML_STATUS_ERROR)
2497       xml_failure(g_parser);
2498     fail("Parse not suspended in CDATA handler");
2499   }
2500   if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE)
2501     xml_failure(g_parser);
2502 }
2503 END_TEST
2504 
2505 /* Test memory allocation functions */
START_TEST(test_memory_allocation)2506 START_TEST(test_memory_allocation) {
2507   char *buffer = (char *)XML_MemMalloc(g_parser, 256);
2508   char *p;
2509 
2510   if (buffer == NULL) {
2511     fail("Allocation failed");
2512   } else {
2513     /* Try writing to memory; some OSes try to cheat! */
2514     buffer[0] = 'T';
2515     buffer[1] = 'E';
2516     buffer[2] = 'S';
2517     buffer[3] = 'T';
2518     buffer[4] = '\0';
2519     if (strcmp(buffer, "TEST") != 0) {
2520       fail("Memory not writable");
2521     } else {
2522       p = (char *)XML_MemRealloc(g_parser, buffer, 512);
2523       if (p == NULL) {
2524         fail("Reallocation failed");
2525       } else {
2526         /* Write again, just to be sure */
2527         buffer = p;
2528         buffer[0] = 'V';
2529         if (strcmp(buffer, "VEST") != 0) {
2530           fail("Reallocated memory not writable");
2531         }
2532       }
2533     }
2534     XML_MemFree(g_parser, buffer);
2535   }
2536 }
2537 END_TEST
2538 
2539 static void XMLCALL
record_default_handler(void * userData,const XML_Char * s,int len)2540 record_default_handler(void *userData, const XML_Char *s, int len) {
2541   UNUSED_P(s);
2542   UNUSED_P(len);
2543   CharData_AppendXMLChars((CharData *)userData, XCS("D"), 1);
2544 }
2545 
2546 static void XMLCALL
record_cdata_handler(void * userData,const XML_Char * s,int len)2547 record_cdata_handler(void *userData, const XML_Char *s, int len) {
2548   UNUSED_P(s);
2549   UNUSED_P(len);
2550   CharData_AppendXMLChars((CharData *)userData, XCS("C"), 1);
2551   XML_DefaultCurrent(g_parser);
2552 }
2553 
2554 static void XMLCALL
record_cdata_nodefault_handler(void * userData,const XML_Char * s,int len)2555 record_cdata_nodefault_handler(void *userData, const XML_Char *s, int len) {
2556   UNUSED_P(s);
2557   UNUSED_P(len);
2558   CharData_AppendXMLChars((CharData *)userData, XCS("c"), 1);
2559 }
2560 
2561 static void XMLCALL
record_skip_handler(void * userData,const XML_Char * entityName,int is_parameter_entity)2562 record_skip_handler(void *userData, const XML_Char *entityName,
2563                     int is_parameter_entity) {
2564   UNUSED_P(entityName);
2565   CharData_AppendXMLChars((CharData *)userData,
2566                           is_parameter_entity ? XCS("E") : XCS("e"), 1);
2567 }
2568 
2569 /* Test XML_DefaultCurrent() passes handling on correctly */
START_TEST(test_default_current)2570 START_TEST(test_default_current) {
2571   const char *text = "<doc>hell]</doc>";
2572   const char *entity_text = "<!DOCTYPE doc [\n"
2573                             "<!ENTITY entity '&#37;'>\n"
2574                             "]>\n"
2575                             "<doc>&entity;</doc>";
2576   CharData storage;
2577 
2578   XML_SetDefaultHandler(g_parser, record_default_handler);
2579   XML_SetCharacterDataHandler(g_parser, record_cdata_handler);
2580   CharData_Init(&storage);
2581   XML_SetUserData(g_parser, &storage);
2582   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2583       == XML_STATUS_ERROR)
2584     xml_failure(g_parser);
2585   CharData_CheckXMLChars(&storage, XCS("DCDCDCDCDCDD"));
2586 
2587   /* Again, without the defaulting */
2588   XML_ParserReset(g_parser, NULL);
2589   XML_SetDefaultHandler(g_parser, record_default_handler);
2590   XML_SetCharacterDataHandler(g_parser, record_cdata_nodefault_handler);
2591   CharData_Init(&storage);
2592   XML_SetUserData(g_parser, &storage);
2593   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2594       == XML_STATUS_ERROR)
2595     xml_failure(g_parser);
2596   CharData_CheckXMLChars(&storage, XCS("DcccccD"));
2597 
2598   /* Now with an internal entity to complicate matters */
2599   XML_ParserReset(g_parser, NULL);
2600   XML_SetDefaultHandler(g_parser, record_default_handler);
2601   XML_SetCharacterDataHandler(g_parser, record_cdata_handler);
2602   CharData_Init(&storage);
2603   XML_SetUserData(g_parser, &storage);
2604   if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text),
2605                               XML_TRUE)
2606       == XML_STATUS_ERROR)
2607     xml_failure(g_parser);
2608   /* The default handler suppresses the entity */
2609   CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDDD"));
2610 
2611   /* Again, with a skip handler */
2612   XML_ParserReset(g_parser, NULL);
2613   XML_SetDefaultHandler(g_parser, record_default_handler);
2614   XML_SetCharacterDataHandler(g_parser, record_cdata_handler);
2615   XML_SetSkippedEntityHandler(g_parser, record_skip_handler);
2616   CharData_Init(&storage);
2617   XML_SetUserData(g_parser, &storage);
2618   if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text),
2619                               XML_TRUE)
2620       == XML_STATUS_ERROR)
2621     xml_failure(g_parser);
2622   /* The default handler suppresses the entity */
2623   CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDeD"));
2624 
2625   /* This time, allow the entity through */
2626   XML_ParserReset(g_parser, NULL);
2627   XML_SetDefaultHandlerExpand(g_parser, record_default_handler);
2628   XML_SetCharacterDataHandler(g_parser, record_cdata_handler);
2629   CharData_Init(&storage);
2630   XML_SetUserData(g_parser, &storage);
2631   if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text),
2632                               XML_TRUE)
2633       == XML_STATUS_ERROR)
2634     xml_failure(g_parser);
2635   CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDCDD"));
2636 
2637   /* Finally, without passing the cdata to the default handler */
2638   XML_ParserReset(g_parser, NULL);
2639   XML_SetDefaultHandlerExpand(g_parser, record_default_handler);
2640   XML_SetCharacterDataHandler(g_parser, record_cdata_nodefault_handler);
2641   CharData_Init(&storage);
2642   XML_SetUserData(g_parser, &storage);
2643   if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text),
2644                               XML_TRUE)
2645       == XML_STATUS_ERROR)
2646     xml_failure(g_parser);
2647   CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDcD"));
2648 }
2649 END_TEST
2650 
2651 /* Test DTD element parsing code paths */
START_TEST(test_dtd_elements)2652 START_TEST(test_dtd_elements) {
2653   const char *text = "<!DOCTYPE doc [\n"
2654                      "<!ELEMENT doc (chapter)>\n"
2655                      "<!ELEMENT chapter (#PCDATA)>\n"
2656                      "]>\n"
2657                      "<doc><chapter>Wombats are go</chapter></doc>";
2658 
2659   XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
2660   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2661       == XML_STATUS_ERROR)
2662     xml_failure(g_parser);
2663 }
2664 END_TEST
2665 
2666 static void XMLCALL
element_decl_check_model(void * userData,const XML_Char * name,XML_Content * model)2667 element_decl_check_model(void *userData, const XML_Char *name,
2668                          XML_Content *model) {
2669   UNUSED_P(userData);
2670   uint32_t errorFlags = 0;
2671 
2672   /* Expected model array structure is this:
2673    * [0] (type 6, quant 0)
2674    *   [1] (type 5, quant 0)
2675    *     [3] (type 4, quant 0, name "bar")
2676    *     [4] (type 4, quant 0, name "foo")
2677    *     [5] (type 4, quant 3, name "xyz")
2678    *   [2] (type 4, quant 2, name "zebra")
2679    */
2680   errorFlags |= ((xcstrcmp(name, XCS("junk")) == 0) ? 0 : (1u << 0));
2681   errorFlags |= ((model != NULL) ? 0 : (1u << 1));
2682 
2683   errorFlags |= ((model[0].type == XML_CTYPE_SEQ) ? 0 : (1u << 2));
2684   errorFlags |= ((model[0].quant == XML_CQUANT_NONE) ? 0 : (1u << 3));
2685   errorFlags |= ((model[0].numchildren == 2) ? 0 : (1u << 4));
2686   errorFlags |= ((model[0].children == &model[1]) ? 0 : (1u << 5));
2687   errorFlags |= ((model[0].name == NULL) ? 0 : (1u << 6));
2688 
2689   errorFlags |= ((model[1].type == XML_CTYPE_CHOICE) ? 0 : (1u << 7));
2690   errorFlags |= ((model[1].quant == XML_CQUANT_NONE) ? 0 : (1u << 8));
2691   errorFlags |= ((model[1].numchildren == 3) ? 0 : (1u << 9));
2692   errorFlags |= ((model[1].children == &model[3]) ? 0 : (1u << 10));
2693   errorFlags |= ((model[1].name == NULL) ? 0 : (1u << 11));
2694 
2695   errorFlags |= ((model[2].type == XML_CTYPE_NAME) ? 0 : (1u << 12));
2696   errorFlags |= ((model[2].quant == XML_CQUANT_REP) ? 0 : (1u << 13));
2697   errorFlags |= ((model[2].numchildren == 0) ? 0 : (1u << 14));
2698   errorFlags |= ((model[2].children == NULL) ? 0 : (1u << 15));
2699   errorFlags |= ((xcstrcmp(model[2].name, XCS("zebra")) == 0) ? 0 : (1u << 16));
2700 
2701   errorFlags |= ((model[3].type == XML_CTYPE_NAME) ? 0 : (1u << 17));
2702   errorFlags |= ((model[3].quant == XML_CQUANT_NONE) ? 0 : (1u << 18));
2703   errorFlags |= ((model[3].numchildren == 0) ? 0 : (1u << 19));
2704   errorFlags |= ((model[3].children == NULL) ? 0 : (1u << 20));
2705   errorFlags |= ((xcstrcmp(model[3].name, XCS("bar")) == 0) ? 0 : (1u << 21));
2706 
2707   errorFlags |= ((model[4].type == XML_CTYPE_NAME) ? 0 : (1u << 22));
2708   errorFlags |= ((model[4].quant == XML_CQUANT_NONE) ? 0 : (1u << 23));
2709   errorFlags |= ((model[4].numchildren == 0) ? 0 : (1u << 24));
2710   errorFlags |= ((model[4].children == NULL) ? 0 : (1u << 25));
2711   errorFlags |= ((xcstrcmp(model[4].name, XCS("foo")) == 0) ? 0 : (1u << 26));
2712 
2713   errorFlags |= ((model[5].type == XML_CTYPE_NAME) ? 0 : (1u << 27));
2714   errorFlags |= ((model[5].quant == XML_CQUANT_PLUS) ? 0 : (1u << 28));
2715   errorFlags |= ((model[5].numchildren == 0) ? 0 : (1u << 29));
2716   errorFlags |= ((model[5].children == NULL) ? 0 : (1u << 30));
2717   errorFlags |= ((xcstrcmp(model[5].name, XCS("xyz")) == 0) ? 0 : (1u << 31));
2718 
2719   XML_SetUserData(g_parser, (void *)(uintptr_t)errorFlags);
2720   XML_FreeContentModel(g_parser, model);
2721 }
2722 
START_TEST(test_dtd_elements_nesting)2723 START_TEST(test_dtd_elements_nesting) {
2724   // Payload inspired by a test in Perl's XML::Parser
2725   const char *text = "<!DOCTYPE foo [\n"
2726                      "<!ELEMENT junk ((bar|foo|xyz+), zebra*)>\n"
2727                      "]>\n"
2728                      "<foo/>";
2729 
2730   XML_SetUserData(g_parser, (void *)(uintptr_t)-1);
2731 
2732   XML_SetElementDeclHandler(g_parser, element_decl_check_model);
2733   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
2734       == XML_STATUS_ERROR)
2735     xml_failure(g_parser);
2736 
2737   if ((uint32_t)(uintptr_t)XML_GetUserData(g_parser) != 0)
2738     fail("Element declaration model regression detected");
2739 }
2740 END_TEST
2741 
2742 /* Test foreign DTD handling */
START_TEST(test_set_foreign_dtd)2743 START_TEST(test_set_foreign_dtd) {
2744   const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n";
2745   const char *text2 = "<doc>&entity;</doc>";
2746   ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
2747 
2748   /* Check hash salt is passed through too */
2749   XML_SetHashSalt(g_parser, 0x12345678);
2750   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2751   XML_SetUserData(g_parser, &test_data);
2752   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
2753   /* Add a default handler to exercise more code paths */
2754   XML_SetDefaultHandler(g_parser, dummy_default_handler);
2755   if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE)
2756     fail("Could not set foreign DTD");
2757   if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
2758       == XML_STATUS_ERROR)
2759     xml_failure(g_parser);
2760 
2761   /* Ensure that trying to set the DTD after parsing has started
2762    * is faulted, even if it's the same setting.
2763    */
2764   if (XML_UseForeignDTD(g_parser, XML_TRUE)
2765       != XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING)
2766     fail("Failed to reject late foreign DTD setting");
2767   /* Ditto for the hash salt */
2768   if (XML_SetHashSalt(g_parser, 0x23456789))
2769     fail("Failed to reject late hash salt change");
2770 
2771   /* Now finish the parse */
2772   if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
2773       == XML_STATUS_ERROR)
2774     xml_failure(g_parser);
2775 }
2776 END_TEST
2777 
2778 /* Test foreign DTD handling with a failing NotStandalone handler */
START_TEST(test_foreign_dtd_not_standalone)2779 START_TEST(test_foreign_dtd_not_standalone) {
2780   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
2781                      "<doc>&entity;</doc>";
2782   ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
2783 
2784   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2785   XML_SetUserData(g_parser, &test_data);
2786   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
2787   XML_SetNotStandaloneHandler(g_parser, reject_not_standalone_handler);
2788   if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE)
2789     fail("Could not set foreign DTD");
2790   expect_failure(text, XML_ERROR_NOT_STANDALONE,
2791                  "NotStandalonehandler failed to reject");
2792 }
2793 END_TEST
2794 
2795 /* Test invalid character in a foreign DTD is faulted */
START_TEST(test_invalid_foreign_dtd)2796 START_TEST(test_invalid_foreign_dtd) {
2797   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
2798                      "<doc>&entity;</doc>";
2799   ExtFaults test_data
2800       = {"$", "Dollar not faulted", NULL, XML_ERROR_INVALID_TOKEN};
2801 
2802   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2803   XML_SetUserData(g_parser, &test_data);
2804   XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
2805   XML_UseForeignDTD(g_parser, XML_TRUE);
2806   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
2807                  "Bad DTD should not have been accepted");
2808 }
2809 END_TEST
2810 
2811 /* Test foreign DTD use with a doctype */
START_TEST(test_foreign_dtd_with_doctype)2812 START_TEST(test_foreign_dtd_with_doctype) {
2813   const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n"
2814                       "<!DOCTYPE doc [<!ENTITY entity 'hello world'>]>\n";
2815   const char *text2 = "<doc>&entity;</doc>";
2816   ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
2817 
2818   /* Check hash salt is passed through too */
2819   XML_SetHashSalt(g_parser, 0x12345678);
2820   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2821   XML_SetUserData(g_parser, &test_data);
2822   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
2823   /* Add a default handler to exercise more code paths */
2824   XML_SetDefaultHandler(g_parser, dummy_default_handler);
2825   if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE)
2826     fail("Could not set foreign DTD");
2827   if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
2828       == XML_STATUS_ERROR)
2829     xml_failure(g_parser);
2830 
2831   /* Ensure that trying to set the DTD after parsing has started
2832    * is faulted, even if it's the same setting.
2833    */
2834   if (XML_UseForeignDTD(g_parser, XML_TRUE)
2835       != XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING)
2836     fail("Failed to reject late foreign DTD setting");
2837   /* Ditto for the hash salt */
2838   if (XML_SetHashSalt(g_parser, 0x23456789))
2839     fail("Failed to reject late hash salt change");
2840 
2841   /* Now finish the parse */
2842   if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
2843       == XML_STATUS_ERROR)
2844     xml_failure(g_parser);
2845 }
2846 END_TEST
2847 
2848 /* Test XML_UseForeignDTD with no external subset present */
2849 static int XMLCALL
external_entity_null_loader(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)2850 external_entity_null_loader(XML_Parser parser, const XML_Char *context,
2851                             const XML_Char *base, const XML_Char *systemId,
2852                             const XML_Char *publicId) {
2853   UNUSED_P(parser);
2854   UNUSED_P(context);
2855   UNUSED_P(base);
2856   UNUSED_P(systemId);
2857   UNUSED_P(publicId);
2858   return XML_STATUS_OK;
2859 }
2860 
START_TEST(test_foreign_dtd_without_external_subset)2861 START_TEST(test_foreign_dtd_without_external_subset) {
2862   const char *text = "<!DOCTYPE doc [<!ENTITY foo 'bar'>]>\n"
2863                      "<doc>&foo;</doc>";
2864 
2865   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2866   XML_SetUserData(g_parser, NULL);
2867   XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader);
2868   XML_UseForeignDTD(g_parser, XML_TRUE);
2869   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2870       == XML_STATUS_ERROR)
2871     xml_failure(g_parser);
2872 }
2873 END_TEST
2874 
START_TEST(test_empty_foreign_dtd)2875 START_TEST(test_empty_foreign_dtd) {
2876   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
2877                      "<doc>&entity;</doc>";
2878 
2879   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2880   XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader);
2881   XML_UseForeignDTD(g_parser, XML_TRUE);
2882   expect_failure(text, XML_ERROR_UNDEFINED_ENTITY,
2883                  "Undefined entity not faulted");
2884 }
2885 END_TEST
2886 
2887 /* Test XML Base is set and unset appropriately */
START_TEST(test_set_base)2888 START_TEST(test_set_base) {
2889   const XML_Char *old_base;
2890   const XML_Char *new_base = XCS("/local/file/name.xml");
2891 
2892   old_base = XML_GetBase(g_parser);
2893   if (XML_SetBase(g_parser, new_base) != XML_STATUS_OK)
2894     fail("Unable to set base");
2895   if (xcstrcmp(XML_GetBase(g_parser), new_base) != 0)
2896     fail("Base setting not correct");
2897   if (XML_SetBase(g_parser, NULL) != XML_STATUS_OK)
2898     fail("Unable to NULL base");
2899   if (XML_GetBase(g_parser) != NULL)
2900     fail("Base setting not nulled");
2901   XML_SetBase(g_parser, old_base);
2902 }
2903 END_TEST
2904 
2905 /* Test attribute counts, indexing, etc */
2906 typedef struct attrInfo {
2907   const XML_Char *name;
2908   const XML_Char *value;
2909 } AttrInfo;
2910 
2911 typedef struct elementInfo {
2912   const XML_Char *name;
2913   int attr_count;
2914   const XML_Char *id_name;
2915   AttrInfo *attributes;
2916 } ElementInfo;
2917 
2918 static void XMLCALL
counting_start_element_handler(void * userData,const XML_Char * name,const XML_Char ** atts)2919 counting_start_element_handler(void *userData, const XML_Char *name,
2920                                const XML_Char **atts) {
2921   ElementInfo *info = (ElementInfo *)userData;
2922   AttrInfo *attr;
2923   int count, id, i;
2924 
2925   while (info->name != NULL) {
2926     if (! xcstrcmp(name, info->name))
2927       break;
2928     info++;
2929   }
2930   if (info->name == NULL)
2931     fail("Element not recognised");
2932   /* The attribute count is twice what you might expect.  It is a
2933    * count of items in atts, an array which contains alternating
2934    * attribute names and attribute values.  For the naive user this
2935    * is possibly a little unexpected, but it is what the
2936    * documentation in expat.h tells us to expect.
2937    */
2938   count = XML_GetSpecifiedAttributeCount(g_parser);
2939   if (info->attr_count * 2 != count) {
2940     fail("Not got expected attribute count");
2941     return;
2942   }
2943   id = XML_GetIdAttributeIndex(g_parser);
2944   if (id == -1 && info->id_name != NULL) {
2945     fail("ID not present");
2946     return;
2947   }
2948   if (id != -1 && xcstrcmp(atts[id], info->id_name)) {
2949     fail("ID does not have the correct name");
2950     return;
2951   }
2952   for (i = 0; i < info->attr_count; i++) {
2953     attr = info->attributes;
2954     while (attr->name != NULL) {
2955       if (! xcstrcmp(atts[0], attr->name))
2956         break;
2957       attr++;
2958     }
2959     if (attr->name == NULL) {
2960       fail("Attribute not recognised");
2961       return;
2962     }
2963     if (xcstrcmp(atts[1], attr->value)) {
2964       fail("Attribute has wrong value");
2965       return;
2966     }
2967     /* Remember, two entries in atts per attribute (see above) */
2968     atts += 2;
2969   }
2970 }
2971 
START_TEST(test_attributes)2972 START_TEST(test_attributes) {
2973   const char *text = "<!DOCTYPE doc [\n"
2974                      "<!ELEMENT doc (tag)>\n"
2975                      "<!ATTLIST doc id ID #REQUIRED>\n"
2976                      "]>"
2977                      "<doc a='1' id='one' b='2'>"
2978                      "<tag c='3'/>"
2979                      "</doc>";
2980   AttrInfo doc_info[] = {{XCS("a"), XCS("1")},
2981                          {XCS("b"), XCS("2")},
2982                          {XCS("id"), XCS("one")},
2983                          {NULL, NULL}};
2984   AttrInfo tag_info[] = {{XCS("c"), XCS("3")}, {NULL, NULL}};
2985   ElementInfo info[] = {{XCS("doc"), 3, XCS("id"), NULL},
2986                         {XCS("tag"), 1, NULL, NULL},
2987                         {NULL, 0, NULL, NULL}};
2988   info[0].attributes = doc_info;
2989   info[1].attributes = tag_info;
2990 
2991   XML_SetStartElementHandler(g_parser, counting_start_element_handler);
2992   XML_SetUserData(g_parser, info);
2993   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2994       == XML_STATUS_ERROR)
2995     xml_failure(g_parser);
2996 }
2997 END_TEST
2998 
2999 /* Test reset works correctly in the middle of processing an internal
3000  * entity.  Exercises some obscure code in XML_ParserReset().
3001  */
START_TEST(test_reset_in_entity)3002 START_TEST(test_reset_in_entity) {
3003   const char *text = "<!DOCTYPE doc [\n"
3004                      "<!ENTITY wombat 'wom'>\n"
3005                      "<!ENTITY entity 'hi &wom; there'>\n"
3006                      "]>\n"
3007                      "<doc>&entity;</doc>";
3008   XML_ParsingStatus status;
3009 
3010   resumable = XML_TRUE;
3011   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
3012   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
3013       == XML_STATUS_ERROR)
3014     xml_failure(g_parser);
3015   XML_GetParsingStatus(g_parser, &status);
3016   if (status.parsing != XML_SUSPENDED)
3017     fail("Parsing status not SUSPENDED");
3018   XML_ParserReset(g_parser, NULL);
3019   XML_GetParsingStatus(g_parser, &status);
3020   if (status.parsing != XML_INITIALIZED)
3021     fail("Parsing status doesn't reset to INITIALIZED");
3022 }
3023 END_TEST
3024 
3025 /* Test that resume correctly passes through parse errors */
START_TEST(test_resume_invalid_parse)3026 START_TEST(test_resume_invalid_parse) {
3027   const char *text = "<doc>Hello</doc"; /* Missing closing wedge */
3028 
3029   resumable = XML_TRUE;
3030   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
3031   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
3032       == XML_STATUS_ERROR)
3033     xml_failure(g_parser);
3034   if (XML_ResumeParser(g_parser) == XML_STATUS_OK)
3035     fail("Resumed invalid parse not faulted");
3036   if (XML_GetErrorCode(g_parser) != XML_ERROR_UNCLOSED_TOKEN)
3037     fail("Invalid parse not correctly faulted");
3038 }
3039 END_TEST
3040 
3041 /* Test that re-suspended parses are correctly passed through */
START_TEST(test_resume_resuspended)3042 START_TEST(test_resume_resuspended) {
3043   const char *text = "<doc>Hello<meep/>world</doc>";
3044 
3045   resumable = XML_TRUE;
3046   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
3047   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
3048       == XML_STATUS_ERROR)
3049     xml_failure(g_parser);
3050   resumable = XML_TRUE;
3051   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
3052   if (XML_ResumeParser(g_parser) != XML_STATUS_SUSPENDED)
3053     fail("Resumption not suspended");
3054   /* This one should succeed and finish up */
3055   if (XML_ResumeParser(g_parser) != XML_STATUS_OK)
3056     xml_failure(g_parser);
3057 }
3058 END_TEST
3059 
3060 /* Test that CDATA shows up correctly through a default handler */
START_TEST(test_cdata_default)3061 START_TEST(test_cdata_default) {
3062   const char *text = "<doc><![CDATA[Hello\nworld]]></doc>";
3063   const XML_Char *expected = XCS("<doc><![CDATA[Hello\nworld]]></doc>");
3064   CharData storage;
3065 
3066   CharData_Init(&storage);
3067   XML_SetUserData(g_parser, &storage);
3068   XML_SetDefaultHandler(g_parser, accumulate_characters);
3069 
3070   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3071       == XML_STATUS_ERROR)
3072     xml_failure(g_parser);
3073   CharData_CheckXMLChars(&storage, expected);
3074 }
3075 END_TEST
3076 
3077 /* Test resetting a subordinate parser does exactly nothing */
3078 static int XMLCALL
external_entity_resetter(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3079 external_entity_resetter(XML_Parser parser, const XML_Char *context,
3080                          const XML_Char *base, const XML_Char *systemId,
3081                          const XML_Char *publicId) {
3082   const char *text = "<!ELEMENT doc (#PCDATA)*>";
3083   XML_Parser ext_parser;
3084   XML_ParsingStatus status;
3085 
3086   UNUSED_P(base);
3087   UNUSED_P(systemId);
3088   UNUSED_P(publicId);
3089   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3090   if (ext_parser == NULL)
3091     fail("Could not create external entity parser");
3092   XML_GetParsingStatus(ext_parser, &status);
3093   if (status.parsing != XML_INITIALIZED) {
3094     fail("Parsing status is not INITIALIZED");
3095     return XML_STATUS_ERROR;
3096   }
3097   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3098       == XML_STATUS_ERROR) {
3099     xml_failure(parser);
3100     return XML_STATUS_ERROR;
3101   }
3102   XML_GetParsingStatus(ext_parser, &status);
3103   if (status.parsing != XML_FINISHED) {
3104     fail("Parsing status is not FINISHED");
3105     return XML_STATUS_ERROR;
3106   }
3107   /* Check we can't parse here */
3108   if (XML_Parse(ext_parser, text, (int)strlen(text), XML_TRUE)
3109       != XML_STATUS_ERROR)
3110     fail("Parsing when finished not faulted");
3111   if (XML_GetErrorCode(ext_parser) != XML_ERROR_FINISHED)
3112     fail("Parsing when finished faulted with wrong code");
3113   XML_ParserReset(ext_parser, NULL);
3114   XML_GetParsingStatus(ext_parser, &status);
3115   if (status.parsing != XML_FINISHED) {
3116     fail("Parsing status not still FINISHED");
3117     return XML_STATUS_ERROR;
3118   }
3119   XML_ParserFree(ext_parser);
3120   return XML_STATUS_OK;
3121 }
3122 
START_TEST(test_subordinate_reset)3123 START_TEST(test_subordinate_reset) {
3124   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
3125                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
3126                      "<doc>&entity;</doc>";
3127 
3128   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3129   XML_SetExternalEntityRefHandler(g_parser, external_entity_resetter);
3130   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3131       == XML_STATUS_ERROR)
3132     xml_failure(g_parser);
3133 }
3134 END_TEST
3135 
3136 /* Test suspending a subordinate parser */
3137 
3138 static void XMLCALL
entity_suspending_decl_handler(void * userData,const XML_Char * name,XML_Content * model)3139 entity_suspending_decl_handler(void *userData, const XML_Char *name,
3140                                XML_Content *model) {
3141   XML_Parser ext_parser = (XML_Parser)userData;
3142 
3143   UNUSED_P(name);
3144   if (XML_StopParser(ext_parser, XML_TRUE) != XML_STATUS_ERROR)
3145     fail("Attempting to suspend a subordinate parser not faulted");
3146   if (XML_GetErrorCode(ext_parser) != XML_ERROR_SUSPEND_PE)
3147     fail("Suspending subordinate parser get wrong code");
3148   XML_SetElementDeclHandler(ext_parser, NULL);
3149   XML_FreeContentModel(g_parser, model);
3150 }
3151 
3152 static int XMLCALL
external_entity_suspender(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3153 external_entity_suspender(XML_Parser parser, const XML_Char *context,
3154                           const XML_Char *base, const XML_Char *systemId,
3155                           const XML_Char *publicId) {
3156   const char *text = "<!ELEMENT doc (#PCDATA)*>";
3157   XML_Parser ext_parser;
3158 
3159   UNUSED_P(base);
3160   UNUSED_P(systemId);
3161   UNUSED_P(publicId);
3162   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3163   if (ext_parser == NULL)
3164     fail("Could not create external entity parser");
3165   XML_SetElementDeclHandler(ext_parser, entity_suspending_decl_handler);
3166   XML_SetUserData(ext_parser, ext_parser);
3167   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3168       == XML_STATUS_ERROR) {
3169     xml_failure(ext_parser);
3170     return XML_STATUS_ERROR;
3171   }
3172   XML_ParserFree(ext_parser);
3173   return XML_STATUS_OK;
3174 }
3175 
START_TEST(test_subordinate_suspend)3176 START_TEST(test_subordinate_suspend) {
3177   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
3178                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
3179                      "<doc>&entity;</doc>";
3180 
3181   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3182   XML_SetExternalEntityRefHandler(g_parser, external_entity_suspender);
3183   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3184       == XML_STATUS_ERROR)
3185     xml_failure(g_parser);
3186 }
3187 END_TEST
3188 
3189 /* Test suspending a subordinate parser from an XML declaration */
3190 /* Increases code coverage of the tests */
3191 static void XMLCALL
entity_suspending_xdecl_handler(void * userData,const XML_Char * version,const XML_Char * encoding,int standalone)3192 entity_suspending_xdecl_handler(void *userData, const XML_Char *version,
3193                                 const XML_Char *encoding, int standalone) {
3194   XML_Parser ext_parser = (XML_Parser)userData;
3195 
3196   UNUSED_P(version);
3197   UNUSED_P(encoding);
3198   UNUSED_P(standalone);
3199   XML_StopParser(ext_parser, resumable);
3200   XML_SetXmlDeclHandler(ext_parser, NULL);
3201 }
3202 
3203 static int XMLCALL
external_entity_suspend_xmldecl(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3204 external_entity_suspend_xmldecl(XML_Parser parser, const XML_Char *context,
3205                                 const XML_Char *base, const XML_Char *systemId,
3206                                 const XML_Char *publicId) {
3207   const char *text = "<?xml version='1.0' encoding='us-ascii'?>";
3208   XML_Parser ext_parser;
3209   XML_ParsingStatus status;
3210   enum XML_Status rc;
3211 
3212   UNUSED_P(base);
3213   UNUSED_P(systemId);
3214   UNUSED_P(publicId);
3215   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3216   if (ext_parser == NULL)
3217     fail("Could not create external entity parser");
3218   XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
3219   XML_SetUserData(ext_parser, ext_parser);
3220   rc = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
3221   XML_GetParsingStatus(ext_parser, &status);
3222   if (resumable) {
3223     if (rc == XML_STATUS_ERROR)
3224       xml_failure(ext_parser);
3225     if (status.parsing != XML_SUSPENDED)
3226       fail("Ext Parsing status not SUSPENDED");
3227   } else {
3228     if (rc != XML_STATUS_ERROR)
3229       fail("Ext parsing not aborted");
3230     if (XML_GetErrorCode(ext_parser) != XML_ERROR_ABORTED)
3231       xml_failure(ext_parser);
3232     if (status.parsing != XML_FINISHED)
3233       fail("Ext Parsing status not FINISHED");
3234   }
3235 
3236   XML_ParserFree(ext_parser);
3237   return XML_STATUS_OK;
3238 }
3239 
START_TEST(test_subordinate_xdecl_suspend)3240 START_TEST(test_subordinate_xdecl_suspend) {
3241   const char *text
3242       = "<!DOCTYPE doc [\n"
3243         "  <!ENTITY entity SYSTEM 'http://example.org/dummy.ent'>\n"
3244         "]>\n"
3245         "<doc>&entity;</doc>";
3246 
3247   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3248   XML_SetExternalEntityRefHandler(g_parser, external_entity_suspend_xmldecl);
3249   resumable = XML_TRUE;
3250   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3251       == XML_STATUS_ERROR)
3252     xml_failure(g_parser);
3253 }
3254 END_TEST
3255 
START_TEST(test_subordinate_xdecl_abort)3256 START_TEST(test_subordinate_xdecl_abort) {
3257   const char *text
3258       = "<!DOCTYPE doc [\n"
3259         "  <!ENTITY entity SYSTEM 'http://example.org/dummy.ent'>\n"
3260         "]>\n"
3261         "<doc>&entity;</doc>";
3262 
3263   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3264   XML_SetExternalEntityRefHandler(g_parser, external_entity_suspend_xmldecl);
3265   resumable = XML_FALSE;
3266   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3267       == XML_STATUS_ERROR)
3268     xml_failure(g_parser);
3269 }
3270 END_TEST
3271 
3272 /* Test external entity fault handling with suspension */
3273 static int XMLCALL
external_entity_suspending_faulter(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3274 external_entity_suspending_faulter(XML_Parser parser, const XML_Char *context,
3275                                    const XML_Char *base,
3276                                    const XML_Char *systemId,
3277                                    const XML_Char *publicId) {
3278   XML_Parser ext_parser;
3279   ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser);
3280   void *buffer;
3281   int parse_len = (int)strlen(fault->parse_text);
3282 
3283   UNUSED_P(base);
3284   UNUSED_P(systemId);
3285   UNUSED_P(publicId);
3286   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3287   if (ext_parser == NULL)
3288     fail("Could not create external entity parser");
3289   XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
3290   XML_SetUserData(ext_parser, ext_parser);
3291   resumable = XML_TRUE;
3292   buffer = XML_GetBuffer(ext_parser, parse_len);
3293   if (buffer == NULL)
3294     fail("Could not allocate parse buffer");
3295   assert(buffer != NULL);
3296   memcpy(buffer, fault->parse_text, parse_len);
3297   if (XML_ParseBuffer(ext_parser, parse_len, XML_FALSE) != XML_STATUS_SUSPENDED)
3298     fail("XML declaration did not suspend");
3299   if (XML_ResumeParser(ext_parser) != XML_STATUS_OK)
3300     xml_failure(ext_parser);
3301   if (XML_ParseBuffer(ext_parser, 0, XML_TRUE) != XML_STATUS_ERROR)
3302     fail(fault->fail_text);
3303   if (XML_GetErrorCode(ext_parser) != fault->error)
3304     xml_failure(ext_parser);
3305 
3306   XML_ParserFree(ext_parser);
3307   return XML_STATUS_ERROR;
3308 }
3309 
START_TEST(test_ext_entity_invalid_suspended_parse)3310 START_TEST(test_ext_entity_invalid_suspended_parse) {
3311   const char *text = "<!DOCTYPE doc [\n"
3312                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
3313                      "]>\n"
3314                      "<doc>&en;</doc>";
3315   ExtFaults faults[]
3316       = {{"<?xml version='1.0' encoding='us-ascii'?><",
3317           "Incomplete element declaration not faulted", NULL,
3318           XML_ERROR_UNCLOSED_TOKEN},
3319          {/* First two bytes of a three-byte char */
3320           "<?xml version='1.0' encoding='utf-8'?>\xe2\x82",
3321           "Incomplete character not faulted", NULL, XML_ERROR_PARTIAL_CHAR},
3322          {NULL, NULL, NULL, XML_ERROR_NONE}};
3323   ExtFaults *fault;
3324 
3325   for (fault = &faults[0]; fault->parse_text != NULL; fault++) {
3326     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3327     XML_SetExternalEntityRefHandler(g_parser,
3328                                     external_entity_suspending_faulter);
3329     XML_SetUserData(g_parser, fault);
3330     expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
3331                    "Parser did not report external entity error");
3332     XML_ParserReset(g_parser, NULL);
3333   }
3334 }
3335 END_TEST
3336 
3337 /* Test setting an explicit encoding */
START_TEST(test_explicit_encoding)3338 START_TEST(test_explicit_encoding) {
3339   const char *text1 = "<doc>Hello ";
3340   const char *text2 = " World</doc>";
3341 
3342   /* Just check that we can set the encoding to NULL before starting */
3343   if (XML_SetEncoding(g_parser, NULL) != XML_STATUS_OK)
3344     fail("Failed to initialise encoding to NULL");
3345   /* Say we are UTF-8 */
3346   if (XML_SetEncoding(g_parser, XCS("utf-8")) != XML_STATUS_OK)
3347     fail("Failed to set explicit encoding");
3348   if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
3349       == XML_STATUS_ERROR)
3350     xml_failure(g_parser);
3351   /* Try to switch encodings mid-parse */
3352   if (XML_SetEncoding(g_parser, XCS("us-ascii")) != XML_STATUS_ERROR)
3353     fail("Allowed encoding change");
3354   if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
3355       == XML_STATUS_ERROR)
3356     xml_failure(g_parser);
3357   /* Try now the parse is over */
3358   if (XML_SetEncoding(g_parser, NULL) != XML_STATUS_OK)
3359     fail("Failed to unset encoding");
3360 }
3361 END_TEST
3362 
3363 /* Test handling of trailing CR (rather than newline) */
3364 static void XMLCALL
cr_cdata_handler(void * userData,const XML_Char * s,int len)3365 cr_cdata_handler(void *userData, const XML_Char *s, int len) {
3366   int *pfound = (int *)userData;
3367 
3368   /* Internal processing turns the CR into a newline for the
3369    * character data handler, but not for the default handler
3370    */
3371   if (len == 1 && (*s == XCS('\n') || *s == XCS('\r')))
3372     *pfound = 1;
3373 }
3374 
START_TEST(test_trailing_cr)3375 START_TEST(test_trailing_cr) {
3376   const char *text = "<doc>\r";
3377   int found_cr;
3378 
3379   /* Try with a character handler, for code coverage */
3380   XML_SetCharacterDataHandler(g_parser, cr_cdata_handler);
3381   XML_SetUserData(g_parser, &found_cr);
3382   found_cr = 0;
3383   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3384       == XML_STATUS_OK)
3385     fail("Failed to fault unclosed doc");
3386   if (found_cr == 0)
3387     fail("Did not catch the carriage return");
3388   XML_ParserReset(g_parser, NULL);
3389 
3390   /* Now with a default handler instead */
3391   XML_SetDefaultHandler(g_parser, cr_cdata_handler);
3392   XML_SetUserData(g_parser, &found_cr);
3393   found_cr = 0;
3394   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3395       == XML_STATUS_OK)
3396     fail("Failed to fault unclosed doc");
3397   if (found_cr == 0)
3398     fail("Did not catch default carriage return");
3399 }
3400 END_TEST
3401 
3402 /* Test trailing CR in an external entity parse */
3403 static int XMLCALL
external_entity_cr_catcher(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3404 external_entity_cr_catcher(XML_Parser parser, const XML_Char *context,
3405                            const XML_Char *base, const XML_Char *systemId,
3406                            const XML_Char *publicId) {
3407   const char *text = "\r";
3408   XML_Parser ext_parser;
3409 
3410   UNUSED_P(base);
3411   UNUSED_P(systemId);
3412   UNUSED_P(publicId);
3413   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3414   if (ext_parser == NULL)
3415     fail("Could not create external entity parser");
3416   XML_SetCharacterDataHandler(ext_parser, cr_cdata_handler);
3417   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3418       == XML_STATUS_ERROR)
3419     xml_failure(ext_parser);
3420   XML_ParserFree(ext_parser);
3421   return XML_STATUS_OK;
3422 }
3423 
3424 static int XMLCALL
external_entity_bad_cr_catcher(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3425 external_entity_bad_cr_catcher(XML_Parser parser, const XML_Char *context,
3426                                const XML_Char *base, const XML_Char *systemId,
3427                                const XML_Char *publicId) {
3428   const char *text = "<tag>\r";
3429   XML_Parser ext_parser;
3430 
3431   UNUSED_P(base);
3432   UNUSED_P(systemId);
3433   UNUSED_P(publicId);
3434   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3435   if (ext_parser == NULL)
3436     fail("Could not create external entity parser");
3437   XML_SetCharacterDataHandler(ext_parser, cr_cdata_handler);
3438   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3439       == XML_STATUS_OK)
3440     fail("Async entity error not caught");
3441   if (XML_GetErrorCode(ext_parser) != XML_ERROR_ASYNC_ENTITY)
3442     xml_failure(ext_parser);
3443   XML_ParserFree(ext_parser);
3444   return XML_STATUS_OK;
3445 }
3446 
START_TEST(test_ext_entity_trailing_cr)3447 START_TEST(test_ext_entity_trailing_cr) {
3448   const char *text = "<!DOCTYPE doc [\n"
3449                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
3450                      "]>\n"
3451                      "<doc>&en;</doc>";
3452   int found_cr;
3453 
3454   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3455   XML_SetExternalEntityRefHandler(g_parser, external_entity_cr_catcher);
3456   XML_SetUserData(g_parser, &found_cr);
3457   found_cr = 0;
3458   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3459       != XML_STATUS_OK)
3460     xml_failure(g_parser);
3461   if (found_cr == 0)
3462     fail("No carriage return found");
3463   XML_ParserReset(g_parser, NULL);
3464 
3465   /* Try again with a different trailing CR */
3466   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3467   XML_SetExternalEntityRefHandler(g_parser, external_entity_bad_cr_catcher);
3468   XML_SetUserData(g_parser, &found_cr);
3469   found_cr = 0;
3470   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3471       != XML_STATUS_OK)
3472     xml_failure(g_parser);
3473   if (found_cr == 0)
3474     fail("No carriage return found");
3475 }
3476 END_TEST
3477 
3478 /* Test handling of trailing square bracket */
3479 static void XMLCALL
rsqb_handler(void * userData,const XML_Char * s,int len)3480 rsqb_handler(void *userData, const XML_Char *s, int len) {
3481   int *pfound = (int *)userData;
3482 
3483   if (len == 1 && *s == XCS(']'))
3484     *pfound = 1;
3485 }
3486 
START_TEST(test_trailing_rsqb)3487 START_TEST(test_trailing_rsqb) {
3488   const char *text8 = "<doc>]";
3489   const char text16[] = "\xFF\xFE<\000d\000o\000c\000>\000]\000";
3490   int found_rsqb;
3491   int text8_len = (int)strlen(text8);
3492 
3493   XML_SetCharacterDataHandler(g_parser, rsqb_handler);
3494   XML_SetUserData(g_parser, &found_rsqb);
3495   found_rsqb = 0;
3496   if (_XML_Parse_SINGLE_BYTES(g_parser, text8, text8_len, XML_TRUE)
3497       == XML_STATUS_OK)
3498     fail("Failed to fault unclosed doc");
3499   if (found_rsqb == 0)
3500     fail("Did not catch the right square bracket");
3501 
3502   /* Try again with a different encoding */
3503   XML_ParserReset(g_parser, NULL);
3504   XML_SetCharacterDataHandler(g_parser, rsqb_handler);
3505   XML_SetUserData(g_parser, &found_rsqb);
3506   found_rsqb = 0;
3507   if (_XML_Parse_SINGLE_BYTES(g_parser, text16, (int)sizeof(text16) - 1,
3508                               XML_TRUE)
3509       == XML_STATUS_OK)
3510     fail("Failed to fault unclosed doc");
3511   if (found_rsqb == 0)
3512     fail("Did not catch the right square bracket");
3513 
3514   /* And finally with a default handler */
3515   XML_ParserReset(g_parser, NULL);
3516   XML_SetDefaultHandler(g_parser, rsqb_handler);
3517   XML_SetUserData(g_parser, &found_rsqb);
3518   found_rsqb = 0;
3519   if (_XML_Parse_SINGLE_BYTES(g_parser, text16, (int)sizeof(text16) - 1,
3520                               XML_TRUE)
3521       == XML_STATUS_OK)
3522     fail("Failed to fault unclosed doc");
3523   if (found_rsqb == 0)
3524     fail("Did not catch the right square bracket");
3525 }
3526 END_TEST
3527 
3528 /* Test trailing right square bracket in an external entity parse */
3529 static int XMLCALL
external_entity_rsqb_catcher(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3530 external_entity_rsqb_catcher(XML_Parser parser, const XML_Char *context,
3531                              const XML_Char *base, const XML_Char *systemId,
3532                              const XML_Char *publicId) {
3533   const char *text = "<tag>]";
3534   XML_Parser ext_parser;
3535 
3536   UNUSED_P(base);
3537   UNUSED_P(systemId);
3538   UNUSED_P(publicId);
3539   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3540   if (ext_parser == NULL)
3541     fail("Could not create external entity parser");
3542   XML_SetCharacterDataHandler(ext_parser, rsqb_handler);
3543   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3544       != XML_STATUS_ERROR)
3545     fail("Async entity error not caught");
3546   if (XML_GetErrorCode(ext_parser) != XML_ERROR_ASYNC_ENTITY)
3547     xml_failure(ext_parser);
3548   XML_ParserFree(ext_parser);
3549   return XML_STATUS_OK;
3550 }
3551 
START_TEST(test_ext_entity_trailing_rsqb)3552 START_TEST(test_ext_entity_trailing_rsqb) {
3553   const char *text = "<!DOCTYPE doc [\n"
3554                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
3555                      "]>\n"
3556                      "<doc>&en;</doc>";
3557   int found_rsqb;
3558 
3559   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3560   XML_SetExternalEntityRefHandler(g_parser, external_entity_rsqb_catcher);
3561   XML_SetUserData(g_parser, &found_rsqb);
3562   found_rsqb = 0;
3563   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3564       != XML_STATUS_OK)
3565     xml_failure(g_parser);
3566   if (found_rsqb == 0)
3567     fail("No right square bracket found");
3568 }
3569 END_TEST
3570 
3571 /* Test CDATA handling in an external entity */
3572 static int XMLCALL
external_entity_good_cdata_ascii(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3573 external_entity_good_cdata_ascii(XML_Parser parser, const XML_Char *context,
3574                                  const XML_Char *base, const XML_Char *systemId,
3575                                  const XML_Char *publicId) {
3576   const char *text = "<a><![CDATA[<greeting>Hello, world!</greeting>]]></a>";
3577   const XML_Char *expected = XCS("<greeting>Hello, world!</greeting>");
3578   CharData storage;
3579   XML_Parser ext_parser;
3580 
3581   UNUSED_P(base);
3582   UNUSED_P(systemId);
3583   UNUSED_P(publicId);
3584   CharData_Init(&storage);
3585   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3586   if (ext_parser == NULL)
3587     fail("Could not create external entity parser");
3588   XML_SetUserData(ext_parser, &storage);
3589   XML_SetCharacterDataHandler(ext_parser, accumulate_characters);
3590 
3591   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3592       == XML_STATUS_ERROR)
3593     xml_failure(ext_parser);
3594   CharData_CheckXMLChars(&storage, expected);
3595 
3596   XML_ParserFree(ext_parser);
3597   return XML_STATUS_OK;
3598 }
3599 
START_TEST(test_ext_entity_good_cdata)3600 START_TEST(test_ext_entity_good_cdata) {
3601   const char *text = "<!DOCTYPE doc [\n"
3602                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
3603                      "]>\n"
3604                      "<doc>&en;</doc>";
3605 
3606   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3607   XML_SetExternalEntityRefHandler(g_parser, external_entity_good_cdata_ascii);
3608   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3609       != XML_STATUS_OK)
3610     xml_failure(g_parser);
3611 }
3612 END_TEST
3613 
3614 /* Test user parameter settings */
3615 /* Variable holding the expected handler userData */
3616 static void *handler_data = NULL;
3617 /* Count of the number of times the comment handler has been invoked */
3618 static int comment_count = 0;
3619 /* Count of the number of skipped entities */
3620 static int skip_count = 0;
3621 /* Count of the number of times the XML declaration handler is invoked */
3622 static int xdecl_count = 0;
3623 
3624 static void XMLCALL
xml_decl_handler(void * userData,const XML_Char * version,const XML_Char * encoding,int standalone)3625 xml_decl_handler(void *userData, const XML_Char *version,
3626                  const XML_Char *encoding, int standalone) {
3627   UNUSED_P(version);
3628   UNUSED_P(encoding);
3629   if (userData != handler_data)
3630     fail("User data (xml decl) not correctly set");
3631   if (standalone != -1)
3632     fail("Standalone not flagged as not present in XML decl");
3633   xdecl_count++;
3634 }
3635 
3636 static void XMLCALL
param_check_skip_handler(void * userData,const XML_Char * entityName,int is_parameter_entity)3637 param_check_skip_handler(void *userData, const XML_Char *entityName,
3638                          int is_parameter_entity) {
3639   UNUSED_P(entityName);
3640   UNUSED_P(is_parameter_entity);
3641   if (userData != handler_data)
3642     fail("User data (skip) not correctly set");
3643   skip_count++;
3644 }
3645 
3646 static void XMLCALL
data_check_comment_handler(void * userData,const XML_Char * data)3647 data_check_comment_handler(void *userData, const XML_Char *data) {
3648   UNUSED_P(data);
3649   /* Check that the userData passed through is what we expect */
3650   if (userData != handler_data)
3651     fail("User data (parser) not correctly set");
3652   /* Check that the user data in the parser is appropriate */
3653   if (XML_GetUserData(userData) != (void *)1)
3654     fail("User data in parser not correctly set");
3655   comment_count++;
3656 }
3657 
3658 static int XMLCALL
external_entity_param_checker(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3659 external_entity_param_checker(XML_Parser parser, const XML_Char *context,
3660                               const XML_Char *base, const XML_Char *systemId,
3661                               const XML_Char *publicId) {
3662   const char *text = "<!-- Subordinate parser -->\n"
3663                      "<!ELEMENT doc (#PCDATA)*>";
3664   XML_Parser ext_parser;
3665 
3666   UNUSED_P(base);
3667   UNUSED_P(systemId);
3668   UNUSED_P(publicId);
3669   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3670   if (ext_parser == NULL)
3671     fail("Could not create external entity parser");
3672   handler_data = ext_parser;
3673   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3674       == XML_STATUS_ERROR) {
3675     xml_failure(parser);
3676     return XML_STATUS_ERROR;
3677   }
3678   handler_data = parser;
3679   XML_ParserFree(ext_parser);
3680   return XML_STATUS_OK;
3681 }
3682 
START_TEST(test_user_parameters)3683 START_TEST(test_user_parameters) {
3684   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
3685                      "<!-- Primary parse -->\n"
3686                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
3687                      "<doc>&entity;";
3688   const char *epilog = "<!-- Back to primary parser -->\n"
3689                        "</doc>";
3690 
3691   comment_count = 0;
3692   skip_count = 0;
3693   xdecl_count = 0;
3694   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3695   XML_SetXmlDeclHandler(g_parser, xml_decl_handler);
3696   XML_SetExternalEntityRefHandler(g_parser, external_entity_param_checker);
3697   XML_SetCommentHandler(g_parser, data_check_comment_handler);
3698   XML_SetSkippedEntityHandler(g_parser, param_check_skip_handler);
3699   XML_UseParserAsHandlerArg(g_parser);
3700   XML_SetUserData(g_parser, (void *)1);
3701   handler_data = g_parser;
3702   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
3703       == XML_STATUS_ERROR)
3704     xml_failure(g_parser);
3705   if (comment_count != 2)
3706     fail("Comment handler not invoked enough times");
3707   /* Ensure we can't change policy mid-parse */
3708   if (XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_NEVER))
3709     fail("Changed param entity parsing policy while parsing");
3710   if (_XML_Parse_SINGLE_BYTES(g_parser, epilog, (int)strlen(epilog), XML_TRUE)
3711       == XML_STATUS_ERROR)
3712     xml_failure(g_parser);
3713   if (comment_count != 3)
3714     fail("Comment handler not invoked enough times");
3715   if (skip_count != 1)
3716     fail("Skip handler not invoked enough times");
3717   if (xdecl_count != 1)
3718     fail("XML declaration handler not invoked");
3719 }
3720 END_TEST
3721 
3722 /* Test that an explicit external entity handler argument replaces
3723  * the parser as the first argument.
3724  *
3725  * We do not call the first parameter to the external entity handler
3726  * 'parser' for once, since the first time the handler is called it
3727  * will actually be a text string.  We need to be able to access the
3728  * global 'parser' variable to create our external entity parser from,
3729  * since there are code paths we need to ensure get executed.
3730  */
3731 static int XMLCALL
external_entity_ref_param_checker(XML_Parser parameter,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3732 external_entity_ref_param_checker(XML_Parser parameter, const XML_Char *context,
3733                                   const XML_Char *base,
3734                                   const XML_Char *systemId,
3735                                   const XML_Char *publicId) {
3736   const char *text = "<!ELEMENT doc (#PCDATA)*>";
3737   XML_Parser ext_parser;
3738 
3739   UNUSED_P(base);
3740   UNUSED_P(systemId);
3741   UNUSED_P(publicId);
3742   if ((void *)parameter != handler_data)
3743     fail("External entity ref handler parameter not correct");
3744 
3745   /* Here we use the global 'parser' variable */
3746   ext_parser = XML_ExternalEntityParserCreate(g_parser, context, NULL);
3747   if (ext_parser == NULL)
3748     fail("Could not create external entity parser");
3749   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3750       == XML_STATUS_ERROR)
3751     xml_failure(ext_parser);
3752 
3753   XML_ParserFree(ext_parser);
3754   return XML_STATUS_OK;
3755 }
3756 
START_TEST(test_ext_entity_ref_parameter)3757 START_TEST(test_ext_entity_ref_parameter) {
3758   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
3759                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
3760                      "<doc>&entity;</doc>";
3761 
3762   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3763   XML_SetExternalEntityRefHandler(g_parser, external_entity_ref_param_checker);
3764   /* Set a handler arg that is not NULL and not parser (which is
3765    * what NULL would cause to be passed.
3766    */
3767   XML_SetExternalEntityRefHandlerArg(g_parser, (void *)text);
3768   handler_data = (void *)text;
3769   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3770       == XML_STATUS_ERROR)
3771     xml_failure(g_parser);
3772 
3773   /* Now try again with unset args */
3774   XML_ParserReset(g_parser, NULL);
3775   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3776   XML_SetExternalEntityRefHandler(g_parser, external_entity_ref_param_checker);
3777   XML_SetExternalEntityRefHandlerArg(g_parser, NULL);
3778   handler_data = (void *)g_parser;
3779   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3780       == XML_STATUS_ERROR)
3781     xml_failure(g_parser);
3782 }
3783 END_TEST
3784 
3785 /* Test the parsing of an empty string */
START_TEST(test_empty_parse)3786 START_TEST(test_empty_parse) {
3787   const char *text = "<doc></doc>";
3788   const char *partial = "<doc>";
3789 
3790   if (XML_Parse(g_parser, NULL, 0, XML_FALSE) == XML_STATUS_ERROR)
3791     fail("Parsing empty string faulted");
3792   if (XML_Parse(g_parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR)
3793     fail("Parsing final empty string not faulted");
3794   if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_ELEMENTS)
3795     fail("Parsing final empty string faulted for wrong reason");
3796 
3797   /* Now try with valid text before the empty end */
3798   XML_ParserReset(g_parser, NULL);
3799   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
3800       == XML_STATUS_ERROR)
3801     xml_failure(g_parser);
3802   if (XML_Parse(g_parser, NULL, 0, XML_TRUE) == XML_STATUS_ERROR)
3803     fail("Parsing final empty string faulted");
3804 
3805   /* Now try with invalid text before the empty end */
3806   XML_ParserReset(g_parser, NULL);
3807   if (_XML_Parse_SINGLE_BYTES(g_parser, partial, (int)strlen(partial),
3808                               XML_FALSE)
3809       == XML_STATUS_ERROR)
3810     xml_failure(g_parser);
3811   if (XML_Parse(g_parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR)
3812     fail("Parsing final incomplete empty string not faulted");
3813 }
3814 END_TEST
3815 
3816 /* Test odd corners of the XML_GetBuffer interface */
3817 static enum XML_Status
get_feature(enum XML_FeatureEnum feature_id,long * presult)3818 get_feature(enum XML_FeatureEnum feature_id, long *presult) {
3819   const XML_Feature *feature = XML_GetFeatureList();
3820 
3821   if (feature == NULL)
3822     return XML_STATUS_ERROR;
3823   for (; feature->feature != XML_FEATURE_END; feature++) {
3824     if (feature->feature == feature_id) {
3825       *presult = feature->value;
3826       return XML_STATUS_OK;
3827     }
3828   }
3829   return XML_STATUS_ERROR;
3830 }
3831 
3832 /* Having an element name longer than 1024 characters exercises some
3833  * of the pool allocation code in the parser that otherwise does not
3834  * get executed.  The count at the end of the line is the number of
3835  * characters (bytes) in the element name by that point.x
3836  */
3837 static const char *get_buffer_test_text
3838     = "<documentwitharidiculouslylongelementnametotease"  /* 0x030 */
3839       "aparticularcorneroftheallocationinXML_GetBuffers"  /* 0x060 */
3840       "othatwecanimprovethecoverageyetagain012345678901"  /* 0x090 */
3841       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x0c0 */
3842       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x0f0 */
3843       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x120 */
3844       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x150 */
3845       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x180 */
3846       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x1b0 */
3847       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x1e0 */
3848       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x210 */
3849       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x240 */
3850       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x270 */
3851       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x2a0 */
3852       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x2d0 */
3853       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x300 */
3854       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x330 */
3855       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x360 */
3856       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x390 */
3857       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x3c0 */
3858       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x3f0 */
3859       "123456789abcdef0123456789abcdef0123456789>\n<ef0"; /* 0x420 */
3860 
3861 /* Test odd corners of the XML_GetBuffer interface */
START_TEST(test_get_buffer_1)3862 START_TEST(test_get_buffer_1) {
3863   const char *text = get_buffer_test_text;
3864   void *buffer;
3865   long context_bytes;
3866 
3867   /* Attempt to allocate a negative length buffer */
3868   if (XML_GetBuffer(g_parser, -12) != NULL)
3869     fail("Negative length buffer not failed");
3870 
3871   /* Now get a small buffer and extend it past valid length */
3872   buffer = XML_GetBuffer(g_parser, 1536);
3873   if (buffer == NULL)
3874     fail("1.5K buffer failed");
3875   assert(buffer != NULL);
3876   memcpy(buffer, text, strlen(text));
3877   if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE)
3878       == XML_STATUS_ERROR)
3879     xml_failure(g_parser);
3880   if (XML_GetBuffer(g_parser, INT_MAX) != NULL)
3881     fail("INT_MAX buffer not failed");
3882 
3883   /* Now try extending it a more reasonable but still too large
3884    * amount.  The allocator in XML_GetBuffer() doubles the buffer
3885    * size until it exceeds the requested amount or INT_MAX.  If it
3886    * exceeds INT_MAX, it rejects the request, so we want a request
3887    * between INT_MAX and INT_MAX/2.  A gap of 1K seems comfortable,
3888    * with an extra byte just to ensure that the request is off any
3889    * boundary.  The request will be inflated internally by
3890    * XML_CONTEXT_BYTES (if defined), so we subtract that from our
3891    * request.
3892    */
3893   if (get_feature(XML_FEATURE_CONTEXT_BYTES, &context_bytes) != XML_STATUS_OK)
3894     context_bytes = 0;
3895   if (XML_GetBuffer(g_parser, INT_MAX - (context_bytes + 1025)) != NULL)
3896     fail("INT_MAX- buffer not failed");
3897 
3898   /* Now try extending it a carefully crafted amount */
3899   if (XML_GetBuffer(g_parser, 1000) == NULL)
3900     fail("1000 buffer failed");
3901 }
3902 END_TEST
3903 
3904 /* Test more corners of the XML_GetBuffer interface */
START_TEST(test_get_buffer_2)3905 START_TEST(test_get_buffer_2) {
3906   const char *text = get_buffer_test_text;
3907   void *buffer;
3908 
3909   /* Now get a decent buffer */
3910   buffer = XML_GetBuffer(g_parser, 1536);
3911   if (buffer == NULL)
3912     fail("1.5K buffer failed");
3913   assert(buffer != NULL);
3914   memcpy(buffer, text, strlen(text));
3915   if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE)
3916       == XML_STATUS_ERROR)
3917     xml_failure(g_parser);
3918 
3919   /* Extend it, to catch a different code path */
3920   if (XML_GetBuffer(g_parser, 1024) == NULL)
3921     fail("1024 buffer failed");
3922 }
3923 END_TEST
3924 
3925 /* Test for signed integer overflow CVE-2022-23852 */
3926 #if defined(XML_CONTEXT_BYTES)
START_TEST(test_get_buffer_3_overflow)3927 START_TEST(test_get_buffer_3_overflow) {
3928   XML_Parser parser = XML_ParserCreate(NULL);
3929   assert(parser != NULL);
3930 
3931   const char *const text = "\n";
3932   const int expectedKeepValue = (int)strlen(text);
3933 
3934   // After this call, variable "keep" in XML_GetBuffer will
3935   // have value expectedKeepValue
3936   if (XML_Parse(parser, text, (int)strlen(text), XML_FALSE /* isFinal */)
3937       == XML_STATUS_ERROR)
3938     xml_failure(parser);
3939 
3940   assert(expectedKeepValue > 0);
3941   if (XML_GetBuffer(parser, INT_MAX - expectedKeepValue + 1) != NULL)
3942     fail("enlarging buffer not failed");
3943 
3944   XML_ParserFree(parser);
3945 }
3946 END_TEST
3947 #endif // defined(XML_CONTEXT_BYTES)
3948 
3949 /* Test position information macros */
START_TEST(test_byte_info_at_end)3950 START_TEST(test_byte_info_at_end) {
3951   const char *text = "<doc></doc>";
3952 
3953   if (XML_GetCurrentByteIndex(g_parser) != -1
3954       || XML_GetCurrentByteCount(g_parser) != 0)
3955     fail("Byte index/count incorrect at start of parse");
3956   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3957       == XML_STATUS_ERROR)
3958     xml_failure(g_parser);
3959   /* At end, the count will be zero and the index the end of string */
3960   if (XML_GetCurrentByteCount(g_parser) != 0)
3961     fail("Terminal byte count incorrect");
3962   if (XML_GetCurrentByteIndex(g_parser) != (XML_Index)strlen(text))
3963     fail("Terminal byte index incorrect");
3964 }
3965 END_TEST
3966 
3967 /* Test position information from errors */
3968 #define PRE_ERROR_STR "<doc></"
3969 #define POST_ERROR_STR "wombat></doc>"
START_TEST(test_byte_info_at_error)3970 START_TEST(test_byte_info_at_error) {
3971   const char *text = PRE_ERROR_STR POST_ERROR_STR;
3972 
3973   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3974       == XML_STATUS_OK)
3975     fail("Syntax error not faulted");
3976   if (XML_GetCurrentByteCount(g_parser) != 0)
3977     fail("Error byte count incorrect");
3978   if (XML_GetCurrentByteIndex(g_parser) != strlen(PRE_ERROR_STR))
3979     fail("Error byte index incorrect");
3980 }
3981 END_TEST
3982 #undef PRE_ERROR_STR
3983 #undef POST_ERROR_STR
3984 
3985 /* Test position information in handler */
3986 typedef struct ByteTestData {
3987   int start_element_len;
3988   int cdata_len;
3989   int total_string_len;
3990 } ByteTestData;
3991 
3992 static void
byte_character_handler(void * userData,const XML_Char * s,int len)3993 byte_character_handler(void *userData, const XML_Char *s, int len) {
3994 #ifdef XML_CONTEXT_BYTES
3995   int offset, size;
3996   const char *buffer;
3997   ByteTestData *data = (ByteTestData *)userData;
3998 
3999   UNUSED_P(s);
4000   buffer = XML_GetInputContext(g_parser, &offset, &size);
4001   if (buffer == NULL)
4002     fail("Failed to get context buffer");
4003   if (offset != data->start_element_len)
4004     fail("Context offset in unexpected position");
4005   if (len != data->cdata_len)
4006     fail("CDATA length reported incorrectly");
4007   if (size != data->total_string_len)
4008     fail("Context size is not full buffer");
4009   if (XML_GetCurrentByteIndex(g_parser) != offset)
4010     fail("Character byte index incorrect");
4011   if (XML_GetCurrentByteCount(g_parser) != len)
4012     fail("Character byte count incorrect");
4013 #else
4014   UNUSED_P(s);
4015   UNUSED_P(userData);
4016   UNUSED_P(len);
4017 #endif
4018 }
4019 
4020 #define START_ELEMENT "<e>"
4021 #define CDATA_TEXT "Hello"
4022 #define END_ELEMENT "</e>"
START_TEST(test_byte_info_at_cdata)4023 START_TEST(test_byte_info_at_cdata) {
4024   const char *text = START_ELEMENT CDATA_TEXT END_ELEMENT;
4025   int offset, size;
4026   ByteTestData data;
4027 
4028   /* Check initial context is empty */
4029   if (XML_GetInputContext(g_parser, &offset, &size) != NULL)
4030     fail("Unexpected context at start of parse");
4031 
4032   data.start_element_len = (int)strlen(START_ELEMENT);
4033   data.cdata_len = (int)strlen(CDATA_TEXT);
4034   data.total_string_len = (int)strlen(text);
4035   XML_SetCharacterDataHandler(g_parser, byte_character_handler);
4036   XML_SetUserData(g_parser, &data);
4037   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_OK)
4038     xml_failure(g_parser);
4039 }
4040 END_TEST
4041 #undef START_ELEMENT
4042 #undef CDATA_TEXT
4043 #undef END_ELEMENT
4044 
4045 /* Test predefined entities are correctly recognised */
START_TEST(test_predefined_entities)4046 START_TEST(test_predefined_entities) {
4047   const char *text = "<doc>&lt;&gt;&amp;&quot;&apos;</doc>";
4048   const XML_Char *expected = XCS("<doc>&lt;&gt;&amp;&quot;&apos;</doc>");
4049   const XML_Char *result = XCS("<>&\"'");
4050   CharData storage;
4051 
4052   XML_SetDefaultHandler(g_parser, accumulate_characters);
4053   /* run_character_check uses XML_SetCharacterDataHandler(), which
4054    * unfortunately heads off a code path that we need to exercise.
4055    */
4056   CharData_Init(&storage);
4057   XML_SetUserData(g_parser, &storage);
4058   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4059       == XML_STATUS_ERROR)
4060     xml_failure(g_parser);
4061   /* The default handler doesn't translate the entities */
4062   CharData_CheckXMLChars(&storage, expected);
4063 
4064   /* Now try again and check the translation */
4065   XML_ParserReset(g_parser, NULL);
4066   run_character_check(text, result);
4067 }
4068 END_TEST
4069 
4070 /* Regression test that an invalid tag in an external parameter
4071  * reference in an external DTD is correctly faulted.
4072  *
4073  * Only a few specific tags are legal in DTDs ignoring comments and
4074  * processing instructions, all of which begin with an exclamation
4075  * mark.  "<el/>" is not one of them, so the parser should raise an
4076  * error on encountering it.
4077  */
4078 static int XMLCALL
external_entity_param(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)4079 external_entity_param(XML_Parser parser, const XML_Char *context,
4080                       const XML_Char *base, const XML_Char *systemId,
4081                       const XML_Char *publicId) {
4082   const char *text1 = "<!ELEMENT doc EMPTY>\n"
4083                       "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
4084                       "<!ENTITY % e2 '%e1;'>\n"
4085                       "%e1;\n";
4086   const char *text2 = "<!ELEMENT el EMPTY>\n"
4087                       "<el/>\n";
4088   XML_Parser ext_parser;
4089 
4090   UNUSED_P(base);
4091   UNUSED_P(publicId);
4092   if (systemId == NULL)
4093     return XML_STATUS_OK;
4094 
4095   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4096   if (ext_parser == NULL)
4097     fail("Could not create external entity parser");
4098 
4099   if (! xcstrcmp(systemId, XCS("004-1.ent"))) {
4100     if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
4101         != XML_STATUS_ERROR)
4102       fail("Inner DTD with invalid tag not rejected");
4103     if (XML_GetErrorCode(ext_parser) != XML_ERROR_EXTERNAL_ENTITY_HANDLING)
4104       xml_failure(ext_parser);
4105   } else if (! xcstrcmp(systemId, XCS("004-2.ent"))) {
4106     if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE)
4107         != XML_STATUS_ERROR)
4108       fail("Invalid tag in external param not rejected");
4109     if (XML_GetErrorCode(ext_parser) != XML_ERROR_SYNTAX)
4110       xml_failure(ext_parser);
4111   } else {
4112     fail("Unknown system ID");
4113   }
4114 
4115   XML_ParserFree(ext_parser);
4116   return XML_STATUS_ERROR;
4117 }
4118 
START_TEST(test_invalid_tag_in_dtd)4119 START_TEST(test_invalid_tag_in_dtd) {
4120   const char *text = "<!DOCTYPE doc SYSTEM '004-1.ent'>\n"
4121                      "<doc></doc>\n";
4122 
4123   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4124   XML_SetExternalEntityRefHandler(g_parser, external_entity_param);
4125   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
4126                  "Invalid tag IN DTD external param not rejected");
4127 }
4128 END_TEST
4129 
4130 /* Test entities not quite the predefined ones are not mis-recognised */
START_TEST(test_not_predefined_entities)4131 START_TEST(test_not_predefined_entities) {
4132   const char *text[] = {"<doc>&pt;</doc>", "<doc>&amo;</doc>",
4133                         "<doc>&quid;</doc>", "<doc>&apod;</doc>", NULL};
4134   int i = 0;
4135 
4136   while (text[i] != NULL) {
4137     expect_failure(text[i], XML_ERROR_UNDEFINED_ENTITY,
4138                    "Undefined entity not rejected");
4139     XML_ParserReset(g_parser, NULL);
4140     i++;
4141   }
4142 }
4143 END_TEST
4144 
4145 /* Test conditional inclusion (IGNORE) */
4146 static int XMLCALL
external_entity_load_ignore(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)4147 external_entity_load_ignore(XML_Parser parser, const XML_Char *context,
4148                             const XML_Char *base, const XML_Char *systemId,
4149                             const XML_Char *publicId) {
4150   const char *text = "<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>";
4151   XML_Parser ext_parser;
4152 
4153   UNUSED_P(base);
4154   UNUSED_P(systemId);
4155   UNUSED_P(publicId);
4156   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4157   if (ext_parser == NULL)
4158     fail("Could not create external entity parser");
4159   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
4160       == XML_STATUS_ERROR)
4161     xml_failure(parser);
4162 
4163   XML_ParserFree(ext_parser);
4164   return XML_STATUS_OK;
4165 }
4166 
START_TEST(test_ignore_section)4167 START_TEST(test_ignore_section) {
4168   const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
4169                      "<doc><e>&entity;</e></doc>";
4170   const XML_Char *expected
4171       = XCS("<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>\n&entity;");
4172   CharData storage;
4173 
4174   CharData_Init(&storage);
4175   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4176   XML_SetUserData(g_parser, &storage);
4177   XML_SetExternalEntityRefHandler(g_parser, external_entity_load_ignore);
4178   XML_SetDefaultHandler(g_parser, accumulate_characters);
4179   XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler);
4180   XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler);
4181   XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4182   XML_SetStartElementHandler(g_parser, dummy_start_element);
4183   XML_SetEndElementHandler(g_parser, dummy_end_element);
4184   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4185       == XML_STATUS_ERROR)
4186     xml_failure(g_parser);
4187   CharData_CheckXMLChars(&storage, expected);
4188 }
4189 END_TEST
4190 
4191 static int XMLCALL
external_entity_load_ignore_utf16(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)4192 external_entity_load_ignore_utf16(XML_Parser parser, const XML_Char *context,
4193                                   const XML_Char *base,
4194                                   const XML_Char *systemId,
4195                                   const XML_Char *publicId) {
4196   const char text[] =
4197       /* <![IGNORE[<!ELEMENT e (#PCDATA)*>]]> */
4198       "<\0!\0[\0I\0G\0N\0O\0R\0E\0[\0"
4199       "<\0!\0E\0L\0E\0M\0E\0N\0T\0 \0e\0 \0"
4200       "(\0#\0P\0C\0D\0A\0T\0A\0)\0*\0>\0]\0]\0>\0";
4201   XML_Parser ext_parser;
4202 
4203   UNUSED_P(base);
4204   UNUSED_P(systemId);
4205   UNUSED_P(publicId);
4206   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4207   if (ext_parser == NULL)
4208     fail("Could not create external entity parser");
4209   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)sizeof(text) - 1, XML_TRUE)
4210       == XML_STATUS_ERROR)
4211     xml_failure(parser);
4212 
4213   XML_ParserFree(ext_parser);
4214   return XML_STATUS_OK;
4215 }
4216 
START_TEST(test_ignore_section_utf16)4217 START_TEST(test_ignore_section_utf16) {
4218   const char text[] =
4219       /* <!DOCTYPE d SYSTEM 's'> */
4220       "<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 "
4221       "\0S\0Y\0S\0T\0E\0M\0 \0'\0s\0'\0>\0\n\0"
4222       /* <d><e>&en;</e></d> */
4223       "<\0d\0>\0<\0e\0>\0&\0e\0n\0;\0<\0/\0e\0>\0<\0/\0d\0>\0";
4224   const XML_Char *expected = XCS("<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>\n&en;");
4225   CharData storage;
4226 
4227   CharData_Init(&storage);
4228   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4229   XML_SetUserData(g_parser, &storage);
4230   XML_SetExternalEntityRefHandler(g_parser, external_entity_load_ignore_utf16);
4231   XML_SetDefaultHandler(g_parser, accumulate_characters);
4232   XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler);
4233   XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler);
4234   XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4235   XML_SetStartElementHandler(g_parser, dummy_start_element);
4236   XML_SetEndElementHandler(g_parser, dummy_end_element);
4237   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
4238       == XML_STATUS_ERROR)
4239     xml_failure(g_parser);
4240   CharData_CheckXMLChars(&storage, expected);
4241 }
4242 END_TEST
4243 
4244 static int XMLCALL
external_entity_load_ignore_utf16_be(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)4245 external_entity_load_ignore_utf16_be(XML_Parser parser, const XML_Char *context,
4246                                      const XML_Char *base,
4247                                      const XML_Char *systemId,
4248                                      const XML_Char *publicId) {
4249   const char text[] =
4250       /* <![IGNORE[<!ELEMENT e (#PCDATA)*>]]> */
4251       "\0<\0!\0[\0I\0G\0N\0O\0R\0E\0["
4252       "\0<\0!\0E\0L\0E\0M\0E\0N\0T\0 \0e\0 "
4253       "\0(\0#\0P\0C\0D\0A\0T\0A\0)\0*\0>\0]\0]\0>";
4254   XML_Parser ext_parser;
4255 
4256   UNUSED_P(base);
4257   UNUSED_P(systemId);
4258   UNUSED_P(publicId);
4259   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4260   if (ext_parser == NULL)
4261     fail("Could not create external entity parser");
4262   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)sizeof(text) - 1, XML_TRUE)
4263       == XML_STATUS_ERROR)
4264     xml_failure(parser);
4265 
4266   XML_ParserFree(ext_parser);
4267   return XML_STATUS_OK;
4268 }
4269 
START_TEST(test_ignore_section_utf16_be)4270 START_TEST(test_ignore_section_utf16_be) {
4271   const char text[] =
4272       /* <!DOCTYPE d SYSTEM 's'> */
4273       "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 "
4274       "\0S\0Y\0S\0T\0E\0M\0 \0'\0s\0'\0>\0\n"
4275       /* <d><e>&en;</e></d> */
4276       "\0<\0d\0>\0<\0e\0>\0&\0e\0n\0;\0<\0/\0e\0>\0<\0/\0d\0>";
4277   const XML_Char *expected = XCS("<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>\n&en;");
4278   CharData storage;
4279 
4280   CharData_Init(&storage);
4281   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4282   XML_SetUserData(g_parser, &storage);
4283   XML_SetExternalEntityRefHandler(g_parser,
4284                                   external_entity_load_ignore_utf16_be);
4285   XML_SetDefaultHandler(g_parser, accumulate_characters);
4286   XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler);
4287   XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler);
4288   XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4289   XML_SetStartElementHandler(g_parser, dummy_start_element);
4290   XML_SetEndElementHandler(g_parser, dummy_end_element);
4291   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
4292       == XML_STATUS_ERROR)
4293     xml_failure(g_parser);
4294   CharData_CheckXMLChars(&storage, expected);
4295 }
4296 END_TEST
4297 
4298 /* Test mis-formatted conditional exclusion */
START_TEST(test_bad_ignore_section)4299 START_TEST(test_bad_ignore_section) {
4300   const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
4301                      "<doc><e>&entity;</e></doc>";
4302   ExtFaults faults[]
4303       = {{"<![IGNORE[<!ELEM", "Broken-off declaration not faulted", NULL,
4304           XML_ERROR_SYNTAX},
4305          {"<![IGNORE[\x01]]>", "Invalid XML character not faulted", NULL,
4306           XML_ERROR_INVALID_TOKEN},
4307          {/* FIrst two bytes of a three-byte char */
4308           "<![IGNORE[\xe2\x82", "Partial XML character not faulted", NULL,
4309           XML_ERROR_PARTIAL_CHAR},
4310          {NULL, NULL, NULL, XML_ERROR_NONE}};
4311   ExtFaults *fault;
4312 
4313   for (fault = &faults[0]; fault->parse_text != NULL; fault++) {
4314     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4315     XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
4316     XML_SetUserData(g_parser, fault);
4317     expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
4318                    "Incomplete IGNORE section not failed");
4319     XML_ParserReset(g_parser, NULL);
4320   }
4321 }
4322 END_TEST
4323 
4324 /* Test recursive parsing */
4325 static int XMLCALL
external_entity_valuer(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)4326 external_entity_valuer(XML_Parser parser, const XML_Char *context,
4327                        const XML_Char *base, const XML_Char *systemId,
4328                        const XML_Char *publicId) {
4329   const char *text1 = "<!ELEMENT doc EMPTY>\n"
4330                       "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
4331                       "<!ENTITY % e2 '%e1;'>\n"
4332                       "%e1;\n";
4333   XML_Parser ext_parser;
4334 
4335   UNUSED_P(base);
4336   UNUSED_P(publicId);
4337   if (systemId == NULL)
4338     return XML_STATUS_OK;
4339   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4340   if (ext_parser == NULL)
4341     fail("Could not create external entity parser");
4342   if (! xcstrcmp(systemId, XCS("004-1.ent"))) {
4343     if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
4344         == XML_STATUS_ERROR)
4345       xml_failure(ext_parser);
4346   } else if (! xcstrcmp(systemId, XCS("004-2.ent"))) {
4347     ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser);
4348     enum XML_Status status;
4349     enum XML_Error error;
4350 
4351     status = _XML_Parse_SINGLE_BYTES(ext_parser, fault->parse_text,
4352                                      (int)strlen(fault->parse_text), XML_TRUE);
4353     if (fault->error == XML_ERROR_NONE) {
4354       if (status == XML_STATUS_ERROR)
4355         xml_failure(ext_parser);
4356     } else {
4357       if (status != XML_STATUS_ERROR)
4358         fail(fault->fail_text);
4359       error = XML_GetErrorCode(ext_parser);
4360       if (error != fault->error
4361           && (fault->error != XML_ERROR_XML_DECL
4362               || error != XML_ERROR_TEXT_DECL))
4363         xml_failure(ext_parser);
4364     }
4365   }
4366 
4367   XML_ParserFree(ext_parser);
4368   return XML_STATUS_OK;
4369 }
4370 
START_TEST(test_external_entity_values)4371 START_TEST(test_external_entity_values) {
4372   const char *text = "<!DOCTYPE doc SYSTEM '004-1.ent'>\n"
4373                      "<doc></doc>\n";
4374   ExtFaults data_004_2[] = {
4375       {"<!ATTLIST doc a1 CDATA 'value'>", NULL, NULL, XML_ERROR_NONE},
4376       {"<!ATTLIST $doc a1 CDATA 'value'>", "Invalid token not faulted", NULL,
4377        XML_ERROR_INVALID_TOKEN},
4378       {"'wombat", "Unterminated string not faulted", NULL,
4379        XML_ERROR_UNCLOSED_TOKEN},
4380       {"\xe2\x82", "Partial UTF-8 character not faulted", NULL,
4381        XML_ERROR_PARTIAL_CHAR},
4382       {"<?xml version='1.0' encoding='utf-8'?>\n", NULL, NULL, XML_ERROR_NONE},
4383       {"<?xml?>", "Malformed XML declaration not faulted", NULL,
4384        XML_ERROR_XML_DECL},
4385       {/* UTF-8 BOM */
4386        "\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>", NULL, NULL,
4387        XML_ERROR_NONE},
4388       {"<?xml version='1.0' encoding='utf-8'?>\n$",
4389        "Invalid token after text declaration not faulted", NULL,
4390        XML_ERROR_INVALID_TOKEN},
4391       {"<?xml version='1.0' encoding='utf-8'?>\n'wombat",
4392        "Unterminated string after text decl not faulted", NULL,
4393        XML_ERROR_UNCLOSED_TOKEN},
4394       {"<?xml version='1.0' encoding='utf-8'?>\n\xe2\x82",
4395        "Partial UTF-8 character after text decl not faulted", NULL,
4396        XML_ERROR_PARTIAL_CHAR},
4397       {"%e1;", "Recursive parameter entity not faulted", NULL,
4398        XML_ERROR_RECURSIVE_ENTITY_REF},
4399       {NULL, NULL, NULL, XML_ERROR_NONE}};
4400   int i;
4401 
4402   for (i = 0; data_004_2[i].parse_text != NULL; i++) {
4403     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4404     XML_SetExternalEntityRefHandler(g_parser, external_entity_valuer);
4405     XML_SetUserData(g_parser, &data_004_2[i]);
4406     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4407         == XML_STATUS_ERROR)
4408       xml_failure(g_parser);
4409     XML_ParserReset(g_parser, NULL);
4410   }
4411 }
4412 END_TEST
4413 
4414 /* Test the recursive parse interacts with a not standalone handler */
4415 static int XMLCALL
external_entity_not_standalone(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)4416 external_entity_not_standalone(XML_Parser parser, const XML_Char *context,
4417                                const XML_Char *base, const XML_Char *systemId,
4418                                const XML_Char *publicId) {
4419   const char *text1 = "<!ELEMENT doc EMPTY>\n"
4420                       "<!ENTITY % e1 SYSTEM 'bar'>\n"
4421                       "%e1;\n";
4422   const char *text2 = "<!ATTLIST doc a1 CDATA 'value'>";
4423   XML_Parser ext_parser;
4424 
4425   UNUSED_P(base);
4426   UNUSED_P(publicId);
4427   if (systemId == NULL)
4428     return XML_STATUS_OK;
4429   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4430   if (ext_parser == NULL)
4431     fail("Could not create external entity parser");
4432   if (! xcstrcmp(systemId, XCS("foo"))) {
4433     XML_SetNotStandaloneHandler(ext_parser, reject_not_standalone_handler);
4434     if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
4435         != XML_STATUS_ERROR)
4436       fail("Expected not standalone rejection");
4437     if (XML_GetErrorCode(ext_parser) != XML_ERROR_NOT_STANDALONE)
4438       xml_failure(ext_parser);
4439     XML_SetNotStandaloneHandler(ext_parser, NULL);
4440     XML_ParserFree(ext_parser);
4441     return XML_STATUS_ERROR;
4442   } else if (! xcstrcmp(systemId, XCS("bar"))) {
4443     if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE)
4444         == XML_STATUS_ERROR)
4445       xml_failure(ext_parser);
4446   }
4447 
4448   XML_ParserFree(ext_parser);
4449   return XML_STATUS_OK;
4450 }
4451 
START_TEST(test_ext_entity_not_standalone)4452 START_TEST(test_ext_entity_not_standalone) {
4453   const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
4454                      "<doc></doc>";
4455 
4456   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4457   XML_SetExternalEntityRefHandler(g_parser, external_entity_not_standalone);
4458   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
4459                  "Standalone rejection not caught");
4460 }
4461 END_TEST
4462 
4463 static int XMLCALL
external_entity_value_aborter(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)4464 external_entity_value_aborter(XML_Parser parser, const XML_Char *context,
4465                               const XML_Char *base, const XML_Char *systemId,
4466                               const XML_Char *publicId) {
4467   const char *text1 = "<!ELEMENT doc EMPTY>\n"
4468                       "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
4469                       "<!ENTITY % e2 '%e1;'>\n"
4470                       "%e1;\n";
4471   const char *text2 = "<?xml version='1.0' encoding='utf-8'?>";
4472   XML_Parser ext_parser;
4473 
4474   UNUSED_P(base);
4475   UNUSED_P(publicId);
4476   if (systemId == NULL)
4477     return XML_STATUS_OK;
4478   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4479   if (ext_parser == NULL)
4480     fail("Could not create external entity parser");
4481   if (! xcstrcmp(systemId, XCS("004-1.ent"))) {
4482     if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
4483         == XML_STATUS_ERROR)
4484       xml_failure(ext_parser);
4485   }
4486   if (! xcstrcmp(systemId, XCS("004-2.ent"))) {
4487     XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
4488     XML_SetUserData(ext_parser, ext_parser);
4489     if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE)
4490         != XML_STATUS_ERROR)
4491       fail("Aborted parse not faulted");
4492     if (XML_GetErrorCode(ext_parser) != XML_ERROR_ABORTED)
4493       xml_failure(ext_parser);
4494   }
4495 
4496   XML_ParserFree(ext_parser);
4497   return XML_STATUS_OK;
4498 }
4499 
START_TEST(test_ext_entity_value_abort)4500 START_TEST(test_ext_entity_value_abort) {
4501   const char *text = "<!DOCTYPE doc SYSTEM '004-1.ent'>\n"
4502                      "<doc></doc>\n";
4503 
4504   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4505   XML_SetExternalEntityRefHandler(g_parser, external_entity_value_aborter);
4506   resumable = XML_FALSE;
4507   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4508       == XML_STATUS_ERROR)
4509     xml_failure(g_parser);
4510 }
4511 END_TEST
4512 
START_TEST(test_bad_public_doctype)4513 START_TEST(test_bad_public_doctype) {
4514   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
4515                      "<!DOCTYPE doc PUBLIC '{BadName}' 'test'>\n"
4516                      "<doc></doc>";
4517 
4518   /* Setting a handler provokes a particular code path */
4519   XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_handler,
4520                             dummy_end_doctype_handler);
4521   expect_failure(text, XML_ERROR_PUBLICID, "Bad Public ID not failed");
4522 }
4523 END_TEST
4524 
4525 /* Test based on ibm/valid/P32/ibm32v04.xml */
START_TEST(test_attribute_enum_value)4526 START_TEST(test_attribute_enum_value) {
4527   const char *text = "<?xml version='1.0' standalone='no'?>\n"
4528                      "<!DOCTYPE animal SYSTEM 'test.dtd'>\n"
4529                      "<animal>This is a \n    <a/>  \n\nyellow tiger</animal>";
4530   ExtTest dtd_data
4531       = {"<!ELEMENT animal (#PCDATA|a)*>\n"
4532          "<!ELEMENT a EMPTY>\n"
4533          "<!ATTLIST animal xml:space (default|preserve) 'preserve'>",
4534          NULL, NULL};
4535   const XML_Char *expected = XCS("This is a \n      \n\nyellow tiger");
4536 
4537   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
4538   XML_SetUserData(g_parser, &dtd_data);
4539   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4540   /* An attribute list handler provokes a different code path */
4541   XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
4542   run_ext_character_check(text, &dtd_data, expected);
4543 }
4544 END_TEST
4545 
4546 /* Slightly bizarrely, the library seems to silently ignore entity
4547  * definitions for predefined entities, even when they are wrong.  The
4548  * language of the XML 1.0 spec is somewhat unhelpful as to what ought
4549  * to happen, so this is currently treated as acceptable.
4550  */
START_TEST(test_predefined_entity_redefinition)4551 START_TEST(test_predefined_entity_redefinition) {
4552   const char *text = "<!DOCTYPE doc [\n"
4553                      "<!ENTITY apos 'foo'>\n"
4554                      "]>\n"
4555                      "<doc>&apos;</doc>";
4556   run_character_check(text, XCS("'"));
4557 }
4558 END_TEST
4559 
4560 /* Test that the parser stops processing the DTD after an unresolved
4561  * parameter entity is encountered.
4562  */
START_TEST(test_dtd_stop_processing)4563 START_TEST(test_dtd_stop_processing) {
4564   const char *text = "<!DOCTYPE doc [\n"
4565                      "%foo;\n"
4566                      "<!ENTITY bar 'bas'>\n"
4567                      "]><doc/>";
4568 
4569   XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
4570   dummy_handler_flags = 0;
4571   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4572       == XML_STATUS_ERROR)
4573     xml_failure(g_parser);
4574   if (dummy_handler_flags != 0)
4575     fail("DTD processing still going after undefined PE");
4576 }
4577 END_TEST
4578 
4579 /* Test public notations with no system ID */
START_TEST(test_public_notation_no_sysid)4580 START_TEST(test_public_notation_no_sysid) {
4581   const char *text = "<!DOCTYPE doc [\n"
4582                      "<!NOTATION note PUBLIC 'foo'>\n"
4583                      "<!ELEMENT doc EMPTY>\n"
4584                      "]>\n<doc/>";
4585 
4586   dummy_handler_flags = 0;
4587   XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
4588   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4589       == XML_STATUS_ERROR)
4590     xml_failure(g_parser);
4591   if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG)
4592     fail("Notation declaration handler not called");
4593 }
4594 END_TEST
4595 
4596 static void XMLCALL
record_element_start_handler(void * userData,const XML_Char * name,const XML_Char ** atts)4597 record_element_start_handler(void *userData, const XML_Char *name,
4598                              const XML_Char **atts) {
4599   UNUSED_P(atts);
4600   CharData_AppendXMLChars((CharData *)userData, name, (int)xcstrlen(name));
4601 }
4602 
START_TEST(test_nested_groups)4603 START_TEST(test_nested_groups) {
4604   const char *text
4605       = "<!DOCTYPE doc [\n"
4606         "<!ELEMENT doc "
4607         /* Sixteen elements per line */
4608         "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,"
4609         "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?"
4610         "))))))))))))))))))))))))))))))))>\n"
4611         "<!ELEMENT e EMPTY>"
4612         "]>\n"
4613         "<doc><e/></doc>";
4614   CharData storage;
4615 
4616   CharData_Init(&storage);
4617   XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4618   XML_SetStartElementHandler(g_parser, record_element_start_handler);
4619   XML_SetUserData(g_parser, &storage);
4620   dummy_handler_flags = 0;
4621   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4622       == XML_STATUS_ERROR)
4623     xml_failure(g_parser);
4624   CharData_CheckXMLChars(&storage, XCS("doce"));
4625   if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
4626     fail("Element handler not fired");
4627 }
4628 END_TEST
4629 
START_TEST(test_group_choice)4630 START_TEST(test_group_choice) {
4631   const char *text = "<!DOCTYPE doc [\n"
4632                      "<!ELEMENT doc (a|b|c)+>\n"
4633                      "<!ELEMENT a EMPTY>\n"
4634                      "<!ELEMENT b (#PCDATA)>\n"
4635                      "<!ELEMENT c ANY>\n"
4636                      "]>\n"
4637                      "<doc>\n"
4638                      "<a/>\n"
4639                      "<b attr='foo'>This is a foo</b>\n"
4640                      "<c></c>\n"
4641                      "</doc>\n";
4642 
4643   XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4644   dummy_handler_flags = 0;
4645   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4646       == XML_STATUS_ERROR)
4647     xml_failure(g_parser);
4648   if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
4649     fail("Element handler flag not raised");
4650 }
4651 END_TEST
4652 
4653 static int XMLCALL
external_entity_public(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)4654 external_entity_public(XML_Parser parser, const XML_Char *context,
4655                        const XML_Char *base, const XML_Char *systemId,
4656                        const XML_Char *publicId) {
4657   const char *text1 = (const char *)XML_GetUserData(parser);
4658   const char *text2 = "<!ATTLIST doc a CDATA 'value'>";
4659   const char *text = NULL;
4660   XML_Parser ext_parser;
4661   int parse_res;
4662 
4663   UNUSED_P(base);
4664   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4665   if (ext_parser == NULL)
4666     return XML_STATUS_ERROR;
4667   if (systemId != NULL && ! xcstrcmp(systemId, XCS("http://example.org/"))) {
4668     text = text1;
4669   } else if (publicId != NULL && ! xcstrcmp(publicId, XCS("foo"))) {
4670     text = text2;
4671   } else
4672     fail("Unexpected parameters to external entity parser");
4673   assert(text != NULL);
4674   parse_res
4675       = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
4676   XML_ParserFree(ext_parser);
4677   return parse_res;
4678 }
4679 
START_TEST(test_standalone_parameter_entity)4680 START_TEST(test_standalone_parameter_entity) {
4681   const char *text = "<?xml version='1.0' standalone='yes'?>\n"
4682                      "<!DOCTYPE doc SYSTEM 'http://example.org/' [\n"
4683                      "<!ENTITY % entity '<!ELEMENT doc (#PCDATA)>'>\n"
4684                      "%entity;\n"
4685                      "]>\n"
4686                      "<doc></doc>";
4687   char dtd_data[] = "<!ENTITY % e1 'foo'>\n";
4688 
4689   XML_SetUserData(g_parser, dtd_data);
4690   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4691   XML_SetExternalEntityRefHandler(g_parser, external_entity_public);
4692   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4693       == XML_STATUS_ERROR)
4694     xml_failure(g_parser);
4695 }
4696 END_TEST
4697 
4698 /* Test skipping of parameter entity in an external DTD */
4699 /* Derived from ibm/invalid/P69/ibm69i01.xml */
START_TEST(test_skipped_parameter_entity)4700 START_TEST(test_skipped_parameter_entity) {
4701   const char *text = "<?xml version='1.0'?>\n"
4702                      "<!DOCTYPE root SYSTEM 'http://example.org/dtd.ent' [\n"
4703                      "<!ELEMENT root (#PCDATA|a)* >\n"
4704                      "]>\n"
4705                      "<root></root>";
4706   ExtTest dtd_data = {"%pe2;", NULL, NULL};
4707 
4708   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
4709   XML_SetUserData(g_parser, &dtd_data);
4710   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4711   XML_SetSkippedEntityHandler(g_parser, dummy_skip_handler);
4712   dummy_handler_flags = 0;
4713   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4714       == XML_STATUS_ERROR)
4715     xml_failure(g_parser);
4716   if (dummy_handler_flags != DUMMY_SKIP_HANDLER_FLAG)
4717     fail("Skip handler not executed");
4718 }
4719 END_TEST
4720 
4721 /* Test recursive parameter entity definition rejected in external DTD */
START_TEST(test_recursive_external_parameter_entity)4722 START_TEST(test_recursive_external_parameter_entity) {
4723   const char *text = "<?xml version='1.0'?>\n"
4724                      "<!DOCTYPE root SYSTEM 'http://example.org/dtd.ent' [\n"
4725                      "<!ELEMENT root (#PCDATA|a)* >\n"
4726                      "]>\n"
4727                      "<root></root>";
4728   ExtFaults dtd_data = {"<!ENTITY % pe2 '&#37;pe2;'>\n%pe2;",
4729                         "Recursive external parameter entity not faulted", NULL,
4730                         XML_ERROR_RECURSIVE_ENTITY_REF};
4731 
4732   XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
4733   XML_SetUserData(g_parser, &dtd_data);
4734   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4735   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
4736                  "Recursive external parameter not spotted");
4737 }
4738 END_TEST
4739 
4740 /* Test undefined parameter entity in external entity handler */
4741 static int XMLCALL
external_entity_devaluer(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)4742 external_entity_devaluer(XML_Parser parser, const XML_Char *context,
4743                          const XML_Char *base, const XML_Char *systemId,
4744                          const XML_Char *publicId) {
4745   const char *text = "<!ELEMENT doc EMPTY>\n"
4746                      "<!ENTITY % e1 SYSTEM 'bar'>\n"
4747                      "%e1;\n";
4748   XML_Parser ext_parser;
4749   intptr_t clear_handler = (intptr_t)XML_GetUserData(parser);
4750 
4751   UNUSED_P(base);
4752   UNUSED_P(publicId);
4753   if (systemId == NULL || ! xcstrcmp(systemId, XCS("bar")))
4754     return XML_STATUS_OK;
4755   if (xcstrcmp(systemId, XCS("foo")))
4756     fail("Unexpected system ID");
4757   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4758   if (ext_parser == NULL)
4759     fail("Could note create external entity parser");
4760   if (clear_handler)
4761     XML_SetExternalEntityRefHandler(ext_parser, NULL);
4762   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
4763       == XML_STATUS_ERROR)
4764     xml_failure(ext_parser);
4765 
4766   XML_ParserFree(ext_parser);
4767   return XML_STATUS_OK;
4768 }
4769 
START_TEST(test_undefined_ext_entity_in_external_dtd)4770 START_TEST(test_undefined_ext_entity_in_external_dtd) {
4771   const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
4772                      "<doc></doc>\n";
4773 
4774   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4775   XML_SetExternalEntityRefHandler(g_parser, external_entity_devaluer);
4776   XML_SetUserData(g_parser, (void *)(intptr_t)XML_FALSE);
4777   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4778       == XML_STATUS_ERROR)
4779     xml_failure(g_parser);
4780 
4781   /* Now repeat without the external entity ref handler invoking
4782    * another copy of itself.
4783    */
4784   XML_ParserReset(g_parser, NULL);
4785   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4786   XML_SetExternalEntityRefHandler(g_parser, external_entity_devaluer);
4787   XML_SetUserData(g_parser, (void *)(intptr_t)XML_TRUE);
4788   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4789       == XML_STATUS_ERROR)
4790     xml_failure(g_parser);
4791 }
4792 END_TEST
4793 
4794 static void XMLCALL
aborting_xdecl_handler(void * userData,const XML_Char * version,const XML_Char * encoding,int standalone)4795 aborting_xdecl_handler(void *userData, const XML_Char *version,
4796                        const XML_Char *encoding, int standalone) {
4797   UNUSED_P(userData);
4798   UNUSED_P(version);
4799   UNUSED_P(encoding);
4800   UNUSED_P(standalone);
4801   XML_StopParser(g_parser, resumable);
4802   XML_SetXmlDeclHandler(g_parser, NULL);
4803 }
4804 
4805 /* Test suspending the parse on receiving an XML declaration works */
START_TEST(test_suspend_xdecl)4806 START_TEST(test_suspend_xdecl) {
4807   const char *text = long_character_data_text;
4808 
4809   XML_SetXmlDeclHandler(g_parser, aborting_xdecl_handler);
4810   resumable = XML_TRUE;
4811   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4812       != XML_STATUS_SUSPENDED)
4813     xml_failure(g_parser);
4814   if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE)
4815     xml_failure(g_parser);
4816   /* Attempt to start a new parse while suspended */
4817   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
4818       != XML_STATUS_ERROR)
4819     fail("Attempt to parse while suspended not faulted");
4820   if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED)
4821     fail("Suspended parse not faulted with correct error");
4822 }
4823 END_TEST
4824 
4825 /* Test aborting the parse in an epilog works */
4826 static void XMLCALL
selective_aborting_default_handler(void * userData,const XML_Char * s,int len)4827 selective_aborting_default_handler(void *userData, const XML_Char *s, int len) {
4828   const XML_Char *match = (const XML_Char *)userData;
4829 
4830   if (match == NULL
4831       || (xcstrlen(match) == (unsigned)len && ! xcstrncmp(match, s, len))) {
4832     XML_StopParser(g_parser, resumable);
4833     XML_SetDefaultHandler(g_parser, NULL);
4834   }
4835 }
4836 
START_TEST(test_abort_epilog)4837 START_TEST(test_abort_epilog) {
4838   const char *text = "<doc></doc>\n\r\n";
4839   XML_Char match[] = XCS("\r");
4840 
4841   XML_SetDefaultHandler(g_parser, selective_aborting_default_handler);
4842   XML_SetUserData(g_parser, match);
4843   resumable = XML_FALSE;
4844   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4845       != XML_STATUS_ERROR)
4846     fail("Abort not triggered");
4847   if (XML_GetErrorCode(g_parser) != XML_ERROR_ABORTED)
4848     xml_failure(g_parser);
4849 }
4850 END_TEST
4851 
4852 /* Test a different code path for abort in the epilog */
START_TEST(test_abort_epilog_2)4853 START_TEST(test_abort_epilog_2) {
4854   const char *text = "<doc></doc>\n";
4855   XML_Char match[] = XCS("\n");
4856 
4857   XML_SetDefaultHandler(g_parser, selective_aborting_default_handler);
4858   XML_SetUserData(g_parser, match);
4859   resumable = XML_FALSE;
4860   expect_failure(text, XML_ERROR_ABORTED, "Abort not triggered");
4861 }
4862 END_TEST
4863 
4864 /* Test suspension from the epilog */
START_TEST(test_suspend_epilog)4865 START_TEST(test_suspend_epilog) {
4866   const char *text = "<doc></doc>\n";
4867   XML_Char match[] = XCS("\n");
4868 
4869   XML_SetDefaultHandler(g_parser, selective_aborting_default_handler);
4870   XML_SetUserData(g_parser, match);
4871   resumable = XML_TRUE;
4872   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4873       != XML_STATUS_SUSPENDED)
4874     xml_failure(g_parser);
4875 }
4876 END_TEST
4877 
4878 static void XMLCALL
suspending_end_handler(void * userData,const XML_Char * s)4879 suspending_end_handler(void *userData, const XML_Char *s) {
4880   UNUSED_P(s);
4881   XML_StopParser((XML_Parser)userData, 1);
4882 }
4883 
START_TEST(test_suspend_in_sole_empty_tag)4884 START_TEST(test_suspend_in_sole_empty_tag) {
4885   const char *text = "<doc/>";
4886   enum XML_Status rc;
4887 
4888   XML_SetEndElementHandler(g_parser, suspending_end_handler);
4889   XML_SetUserData(g_parser, g_parser);
4890   rc = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE);
4891   if (rc == XML_STATUS_ERROR)
4892     xml_failure(g_parser);
4893   else if (rc != XML_STATUS_SUSPENDED)
4894     fail("Suspend not triggered");
4895   rc = XML_ResumeParser(g_parser);
4896   if (rc == XML_STATUS_ERROR)
4897     xml_failure(g_parser);
4898   else if (rc != XML_STATUS_OK)
4899     fail("Resume failed");
4900 }
4901 END_TEST
4902 
START_TEST(test_unfinished_epilog)4903 START_TEST(test_unfinished_epilog) {
4904   const char *text = "<doc></doc><";
4905 
4906   expect_failure(text, XML_ERROR_UNCLOSED_TOKEN,
4907                  "Incomplete epilog entry not faulted");
4908 }
4909 END_TEST
4910 
START_TEST(test_partial_char_in_epilog)4911 START_TEST(test_partial_char_in_epilog) {
4912   const char *text = "<doc></doc>\xe2\x82";
4913 
4914   /* First check that no fault is raised if the parse is not finished */
4915   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
4916       == XML_STATUS_ERROR)
4917     xml_failure(g_parser);
4918   /* Now check that it is faulted once we finish */
4919   if (XML_ParseBuffer(g_parser, 0, XML_TRUE) != XML_STATUS_ERROR)
4920     fail("Partial character in epilog not faulted");
4921   if (XML_GetErrorCode(g_parser) != XML_ERROR_PARTIAL_CHAR)
4922     xml_failure(g_parser);
4923 }
4924 END_TEST
4925 
START_TEST(test_hash_collision)4926 START_TEST(test_hash_collision) {
4927   /* For full coverage of the lookup routine, we need to ensure a
4928    * hash collision even though we can only tell that we have one
4929    * through breakpoint debugging or coverage statistics.  The
4930    * following will cause a hash collision on machines with a 64-bit
4931    * long type; others will have to experiment.  The full coverage
4932    * tests invoked from qa.sh usually provide a hash collision, but
4933    * not always.  This is an attempt to provide insurance.
4934    */
4935 #define COLLIDING_HASH_SALT (unsigned long)_SIP_ULL(0xffffffffU, 0xff99fc90U)
4936   const char *text
4937       = "<doc>\n"
4938         "<a1/><a2/><a3/><a4/><a5/><a6/><a7/><a8/>\n"
4939         "<b1></b1><b2 attr='foo'>This is a foo</b2><b3></b3><b4></b4>\n"
4940         "<b5></b5><b6></b6><b7></b7><b8></b8>\n"
4941         "<c1/><c2/><c3/><c4/><c5/><c6/><c7/><c8/>\n"
4942         "<d1/><d2/><d3/><d4/><d5/><d6/><d7/>\n"
4943         "<d8>This triggers the table growth and collides with b2</d8>\n"
4944         "</doc>\n";
4945 
4946   XML_SetHashSalt(g_parser, COLLIDING_HASH_SALT);
4947   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4948       == XML_STATUS_ERROR)
4949     xml_failure(g_parser);
4950 }
4951 END_TEST
4952 #undef COLLIDING_HASH_SALT
4953 
4954 /* Test resuming a parse suspended in entity substitution */
4955 static void XMLCALL
start_element_suspender(void * userData,const XML_Char * name,const XML_Char ** atts)4956 start_element_suspender(void *userData, const XML_Char *name,
4957                         const XML_Char **atts) {
4958   UNUSED_P(userData);
4959   UNUSED_P(atts);
4960   if (! xcstrcmp(name, XCS("suspend")))
4961     XML_StopParser(g_parser, XML_TRUE);
4962   if (! xcstrcmp(name, XCS("abort")))
4963     XML_StopParser(g_parser, XML_FALSE);
4964 }
4965 
START_TEST(test_suspend_resume_internal_entity)4966 START_TEST(test_suspend_resume_internal_entity) {
4967   const char *text
4968       = "<!DOCTYPE doc [\n"
4969         "<!ENTITY foo '<suspend>Hi<suspend>Ho</suspend></suspend>'>\n"
4970         "]>\n"
4971         "<doc>&foo;</doc>\n";
4972   const XML_Char *expected1 = XCS("Hi");
4973   const XML_Char *expected2 = XCS("HiHo");
4974   CharData storage;
4975 
4976   CharData_Init(&storage);
4977   XML_SetStartElementHandler(g_parser, start_element_suspender);
4978   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
4979   XML_SetUserData(g_parser, &storage);
4980   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
4981       != XML_STATUS_SUSPENDED)
4982     xml_failure(g_parser);
4983   CharData_CheckXMLChars(&storage, XCS(""));
4984   if (XML_ResumeParser(g_parser) != XML_STATUS_SUSPENDED)
4985     xml_failure(g_parser);
4986   CharData_CheckXMLChars(&storage, expected1);
4987   if (XML_ResumeParser(g_parser) != XML_STATUS_OK)
4988     xml_failure(g_parser);
4989   CharData_CheckXMLChars(&storage, expected2);
4990 }
4991 END_TEST
4992 
4993 /* Test syntax error is caught at parse resumption */
START_TEST(test_resume_entity_with_syntax_error)4994 START_TEST(test_resume_entity_with_syntax_error) {
4995   const char *text = "<!DOCTYPE doc [\n"
4996                      "<!ENTITY foo '<suspend>Hi</wombat>'>\n"
4997                      "]>\n"
4998                      "<doc>&foo;</doc>\n";
4999 
5000   XML_SetStartElementHandler(g_parser, start_element_suspender);
5001   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
5002       != XML_STATUS_SUSPENDED)
5003     xml_failure(g_parser);
5004   if (XML_ResumeParser(g_parser) != XML_STATUS_ERROR)
5005     fail("Syntax error in entity not faulted");
5006   if (XML_GetErrorCode(g_parser) != XML_ERROR_TAG_MISMATCH)
5007     xml_failure(g_parser);
5008 }
5009 END_TEST
5010 
5011 /* Test suspending and resuming in a parameter entity substitution */
5012 static void XMLCALL
element_decl_suspender(void * userData,const XML_Char * name,XML_Content * model)5013 element_decl_suspender(void *userData, const XML_Char *name,
5014                        XML_Content *model) {
5015   UNUSED_P(userData);
5016   UNUSED_P(name);
5017   XML_StopParser(g_parser, XML_TRUE);
5018   XML_FreeContentModel(g_parser, model);
5019 }
5020 
START_TEST(test_suspend_resume_parameter_entity)5021 START_TEST(test_suspend_resume_parameter_entity) {
5022   const char *text = "<!DOCTYPE doc [\n"
5023                      "<!ENTITY % foo '<!ELEMENT doc (#PCDATA)*>'>\n"
5024                      "%foo;\n"
5025                      "]>\n"
5026                      "<doc>Hello, world</doc>";
5027   const XML_Char *expected = XCS("Hello, world");
5028   CharData storage;
5029 
5030   CharData_Init(&storage);
5031   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5032   XML_SetElementDeclHandler(g_parser, element_decl_suspender);
5033   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
5034   XML_SetUserData(g_parser, &storage);
5035   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
5036       != XML_STATUS_SUSPENDED)
5037     xml_failure(g_parser);
5038   CharData_CheckXMLChars(&storage, XCS(""));
5039   if (XML_ResumeParser(g_parser) != XML_STATUS_OK)
5040     xml_failure(g_parser);
5041   CharData_CheckXMLChars(&storage, expected);
5042 }
5043 END_TEST
5044 
5045 /* Test attempting to use parser after an error is faulted */
START_TEST(test_restart_on_error)5046 START_TEST(test_restart_on_error) {
5047   const char *text = "<$doc><doc></doc>";
5048 
5049   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
5050       != XML_STATUS_ERROR)
5051     fail("Invalid tag name not faulted");
5052   if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
5053     xml_failure(g_parser);
5054   if (XML_Parse(g_parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR)
5055     fail("Restarting invalid parse not faulted");
5056   if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
5057     xml_failure(g_parser);
5058 }
5059 END_TEST
5060 
5061 /* Test that angle brackets in an attribute default value are faulted */
START_TEST(test_reject_lt_in_attribute_value)5062 START_TEST(test_reject_lt_in_attribute_value) {
5063   const char *text = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '<bar>'>]>\n"
5064                      "<doc></doc>";
5065 
5066   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5067                  "Bad attribute default not faulted");
5068 }
5069 END_TEST
5070 
START_TEST(test_reject_unfinished_param_in_att_value)5071 START_TEST(test_reject_unfinished_param_in_att_value) {
5072   const char *text = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '&foo'>]>\n"
5073                      "<doc></doc>";
5074 
5075   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5076                  "Bad attribute default not faulted");
5077 }
5078 END_TEST
5079 
START_TEST(test_trailing_cr_in_att_value)5080 START_TEST(test_trailing_cr_in_att_value) {
5081   const char *text = "<doc a='value\r'/>";
5082 
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 /* Try parsing a general entity within a parameter entity in a
5090  * standalone internal DTD.  Covers a corner case in the parser.
5091  */
START_TEST(test_standalone_internal_entity)5092 START_TEST(test_standalone_internal_entity) {
5093   const char *text = "<?xml version='1.0' standalone='yes' ?>\n"
5094                      "<!DOCTYPE doc [\n"
5095                      "  <!ELEMENT doc (#PCDATA)>\n"
5096                      "  <!ENTITY % pe '<!ATTLIST doc att2 CDATA \"&ge;\">'>\n"
5097                      "  <!ENTITY ge 'AttDefaultValue'>\n"
5098                      "  %pe;\n"
5099                      "]>\n"
5100                      "<doc att2='any'/>";
5101 
5102   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5103   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5104       == XML_STATUS_ERROR)
5105     xml_failure(g_parser);
5106 }
5107 END_TEST
5108 
5109 /* Test that a reference to an unknown external entity is skipped */
START_TEST(test_skipped_external_entity)5110 START_TEST(test_skipped_external_entity) {
5111   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
5112                      "<doc></doc>\n";
5113   ExtTest test_data = {"<!ELEMENT doc EMPTY>\n"
5114                        "<!ENTITY % e2 '%e1;'>\n",
5115                        NULL, NULL};
5116 
5117   XML_SetUserData(g_parser, &test_data);
5118   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5119   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
5120   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5121       == XML_STATUS_ERROR)
5122     xml_failure(g_parser);
5123 }
5124 END_TEST
5125 
5126 /* Test a different form of unknown external entity */
5127 typedef struct ext_hdlr_data {
5128   const char *parse_text;
5129   XML_ExternalEntityRefHandler handler;
5130 } ExtHdlrData;
5131 
5132 static int XMLCALL
external_entity_oneshot_loader(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)5133 external_entity_oneshot_loader(XML_Parser parser, const XML_Char *context,
5134                                const XML_Char *base, const XML_Char *systemId,
5135                                const XML_Char *publicId) {
5136   ExtHdlrData *test_data = (ExtHdlrData *)XML_GetUserData(parser);
5137   XML_Parser ext_parser;
5138 
5139   UNUSED_P(base);
5140   UNUSED_P(systemId);
5141   UNUSED_P(publicId);
5142   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
5143   if (ext_parser == NULL)
5144     fail("Could not create external entity parser.");
5145   /* Use the requested entity parser for further externals */
5146   XML_SetExternalEntityRefHandler(ext_parser, test_data->handler);
5147   if (_XML_Parse_SINGLE_BYTES(ext_parser, test_data->parse_text,
5148                               (int)strlen(test_data->parse_text), XML_TRUE)
5149       == XML_STATUS_ERROR) {
5150     xml_failure(ext_parser);
5151   }
5152 
5153   XML_ParserFree(ext_parser);
5154   return XML_STATUS_OK;
5155 }
5156 
START_TEST(test_skipped_null_loaded_ext_entity)5157 START_TEST(test_skipped_null_loaded_ext_entity) {
5158   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n"
5159                      "<doc />";
5160   ExtHdlrData test_data
5161       = {"<!ENTITY % pe1 SYSTEM 'http://example.org/two.ent'>\n"
5162          "<!ENTITY % pe2 '%pe1;'>\n"
5163          "%pe2;\n",
5164          external_entity_null_loader};
5165 
5166   XML_SetUserData(g_parser, &test_data);
5167   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5168   XML_SetExternalEntityRefHandler(g_parser, external_entity_oneshot_loader);
5169   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5170       == XML_STATUS_ERROR)
5171     xml_failure(g_parser);
5172 }
5173 END_TEST
5174 
START_TEST(test_skipped_unloaded_ext_entity)5175 START_TEST(test_skipped_unloaded_ext_entity) {
5176   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n"
5177                      "<doc />";
5178   ExtHdlrData test_data
5179       = {"<!ENTITY % pe1 SYSTEM 'http://example.org/two.ent'>\n"
5180          "<!ENTITY % pe2 '%pe1;'>\n"
5181          "%pe2;\n",
5182          NULL};
5183 
5184   XML_SetUserData(g_parser, &test_data);
5185   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5186   XML_SetExternalEntityRefHandler(g_parser, external_entity_oneshot_loader);
5187   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5188       == XML_STATUS_ERROR)
5189     xml_failure(g_parser);
5190 }
5191 END_TEST
5192 
5193 /* Test that a parameter entity value ending with a carriage return
5194  * has it translated internally into a newline.
5195  */
START_TEST(test_param_entity_with_trailing_cr)5196 START_TEST(test_param_entity_with_trailing_cr) {
5197 #define PARAM_ENTITY_NAME "pe"
5198 #define PARAM_ENTITY_CORE_VALUE "<!ATTLIST doc att CDATA \"default\">"
5199   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
5200                      "<doc/>";
5201   ExtTest test_data
5202       = {"<!ENTITY % " PARAM_ENTITY_NAME " '" PARAM_ENTITY_CORE_VALUE "\r'>\n"
5203          "%" PARAM_ENTITY_NAME ";\n",
5204          NULL, NULL};
5205 
5206   XML_SetUserData(g_parser, &test_data);
5207   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5208   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
5209   XML_SetEntityDeclHandler(g_parser, param_entity_match_handler);
5210   entity_name_to_match = XCS(PARAM_ENTITY_NAME);
5211   entity_value_to_match = XCS(PARAM_ENTITY_CORE_VALUE) XCS("\n");
5212   entity_match_flag = ENTITY_MATCH_NOT_FOUND;
5213   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5214       == XML_STATUS_ERROR)
5215     xml_failure(g_parser);
5216   if (entity_match_flag == ENTITY_MATCH_FAIL)
5217     fail("Parameter entity CR->NEWLINE conversion failed");
5218   else if (entity_match_flag == ENTITY_MATCH_NOT_FOUND)
5219     fail("Parameter entity not parsed");
5220 }
5221 #undef PARAM_ENTITY_NAME
5222 #undef PARAM_ENTITY_CORE_VALUE
5223 END_TEST
5224 
START_TEST(test_invalid_character_entity)5225 START_TEST(test_invalid_character_entity) {
5226   const char *text = "<!DOCTYPE doc [\n"
5227                      "  <!ENTITY entity '&#x110000;'>\n"
5228                      "]>\n"
5229                      "<doc>&entity;</doc>";
5230 
5231   expect_failure(text, XML_ERROR_BAD_CHAR_REF,
5232                  "Out of range character reference not faulted");
5233 }
5234 END_TEST
5235 
START_TEST(test_invalid_character_entity_2)5236 START_TEST(test_invalid_character_entity_2) {
5237   const char *text = "<!DOCTYPE doc [\n"
5238                      "  <!ENTITY entity '&#xg0;'>\n"
5239                      "]>\n"
5240                      "<doc>&entity;</doc>";
5241 
5242   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5243                  "Out of range character reference not faulted");
5244 }
5245 END_TEST
5246 
START_TEST(test_invalid_character_entity_3)5247 START_TEST(test_invalid_character_entity_3) {
5248   const char text[] =
5249       /* <!DOCTYPE doc [\n */
5250       "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0\n"
5251       /* U+0E04 = KHO KHWAI
5252        * U+0E08 = CHO CHAN */
5253       /* <!ENTITY entity '&\u0e04\u0e08;'>\n */
5254       "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0e\0n\0t\0i\0t\0y\0 "
5255       "\0'\0&\x0e\x04\x0e\x08\0;\0'\0>\0\n"
5256       /* ]>\n */
5257       "\0]\0>\0\n"
5258       /* <doc>&entity;</doc> */
5259       "\0<\0d\0o\0c\0>\0&\0e\0n\0t\0i\0t\0y\0;\0<\0/\0d\0o\0c\0>";
5260 
5261   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5262       != XML_STATUS_ERROR)
5263     fail("Invalid start of entity name not faulted");
5264   if (XML_GetErrorCode(g_parser) != XML_ERROR_UNDEFINED_ENTITY)
5265     xml_failure(g_parser);
5266 }
5267 END_TEST
5268 
START_TEST(test_invalid_character_entity_4)5269 START_TEST(test_invalid_character_entity_4) {
5270   const char *text = "<!DOCTYPE doc [\n"
5271                      "  <!ENTITY entity '&#1114112;'>\n" /* = &#x110000 */
5272                      "]>\n"
5273                      "<doc>&entity;</doc>";
5274 
5275   expect_failure(text, XML_ERROR_BAD_CHAR_REF,
5276                  "Out of range character reference not faulted");
5277 }
5278 END_TEST
5279 
5280 /* Test that processing instructions are picked up by a default handler */
START_TEST(test_pi_handled_in_default)5281 START_TEST(test_pi_handled_in_default) {
5282   const char *text = "<?test processing instruction?>\n<doc/>";
5283   const XML_Char *expected = XCS("<?test processing instruction?>\n<doc/>");
5284   CharData storage;
5285 
5286   CharData_Init(&storage);
5287   XML_SetDefaultHandler(g_parser, accumulate_characters);
5288   XML_SetUserData(g_parser, &storage);
5289   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5290       == XML_STATUS_ERROR)
5291     xml_failure(g_parser);
5292   CharData_CheckXMLChars(&storage, expected);
5293 }
5294 END_TEST
5295 
5296 /* Test that comments are picked up by a default handler */
START_TEST(test_comment_handled_in_default)5297 START_TEST(test_comment_handled_in_default) {
5298   const char *text = "<!-- This is a comment -->\n<doc/>";
5299   const XML_Char *expected = XCS("<!-- This is a comment -->\n<doc/>");
5300   CharData storage;
5301 
5302   CharData_Init(&storage);
5303   XML_SetDefaultHandler(g_parser, accumulate_characters);
5304   XML_SetUserData(g_parser, &storage);
5305   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5306       == XML_STATUS_ERROR)
5307     xml_failure(g_parser);
5308   CharData_CheckXMLChars(&storage, expected);
5309 }
5310 END_TEST
5311 
5312 /* Test PIs that look almost but not quite like XML declarations */
5313 static void XMLCALL
accumulate_pi_characters(void * userData,const XML_Char * target,const XML_Char * data)5314 accumulate_pi_characters(void *userData, const XML_Char *target,
5315                          const XML_Char *data) {
5316   CharData *storage = (CharData *)userData;
5317 
5318   CharData_AppendXMLChars(storage, target, -1);
5319   CharData_AppendXMLChars(storage, XCS(": "), 2);
5320   CharData_AppendXMLChars(storage, data, -1);
5321   CharData_AppendXMLChars(storage, XCS("\n"), 1);
5322 }
5323 
START_TEST(test_pi_yml)5324 START_TEST(test_pi_yml) {
5325   const char *text = "<?yml something like data?><doc/>";
5326   const XML_Char *expected = XCS("yml: something like data\n");
5327   CharData storage;
5328 
5329   CharData_Init(&storage);
5330   XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5331   XML_SetUserData(g_parser, &storage);
5332   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5333       == XML_STATUS_ERROR)
5334     xml_failure(g_parser);
5335   CharData_CheckXMLChars(&storage, expected);
5336 }
5337 END_TEST
5338 
START_TEST(test_pi_xnl)5339 START_TEST(test_pi_xnl) {
5340   const char *text = "<?xnl nothing like data?><doc/>";
5341   const XML_Char *expected = XCS("xnl: nothing like data\n");
5342   CharData storage;
5343 
5344   CharData_Init(&storage);
5345   XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5346   XML_SetUserData(g_parser, &storage);
5347   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5348       == XML_STATUS_ERROR)
5349     xml_failure(g_parser);
5350   CharData_CheckXMLChars(&storage, expected);
5351 }
5352 END_TEST
5353 
START_TEST(test_pi_xmm)5354 START_TEST(test_pi_xmm) {
5355   const char *text = "<?xmm everything like data?><doc/>";
5356   const XML_Char *expected = XCS("xmm: everything like data\n");
5357   CharData storage;
5358 
5359   CharData_Init(&storage);
5360   XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5361   XML_SetUserData(g_parser, &storage);
5362   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5363       == XML_STATUS_ERROR)
5364     xml_failure(g_parser);
5365   CharData_CheckXMLChars(&storage, expected);
5366 }
5367 END_TEST
5368 
START_TEST(test_utf16_pi)5369 START_TEST(test_utf16_pi) {
5370   const char text[] =
5371       /* <?{KHO KHWAI}{CHO CHAN}?>
5372        * where {KHO KHWAI} = U+0E04
5373        * and   {CHO CHAN}  = U+0E08
5374        */
5375       "<\0?\0\x04\x0e\x08\x0e?\0>\0"
5376       /* <q/> */
5377       "<\0q\0/\0>\0";
5378 #ifdef XML_UNICODE
5379   const XML_Char *expected = XCS("\x0e04\x0e08: \n");
5380 #else
5381   const XML_Char *expected = XCS("\xe0\xb8\x84\xe0\xb8\x88: \n");
5382 #endif
5383   CharData storage;
5384 
5385   CharData_Init(&storage);
5386   XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5387   XML_SetUserData(g_parser, &storage);
5388   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5389       == XML_STATUS_ERROR)
5390     xml_failure(g_parser);
5391   CharData_CheckXMLChars(&storage, expected);
5392 }
5393 END_TEST
5394 
START_TEST(test_utf16_be_pi)5395 START_TEST(test_utf16_be_pi) {
5396   const char text[] =
5397       /* <?{KHO KHWAI}{CHO CHAN}?>
5398        * where {KHO KHWAI} = U+0E04
5399        * and   {CHO CHAN}  = U+0E08
5400        */
5401       "\0<\0?\x0e\x04\x0e\x08\0?\0>"
5402       /* <q/> */
5403       "\0<\0q\0/\0>";
5404 #ifdef XML_UNICODE
5405   const XML_Char *expected = XCS("\x0e04\x0e08: \n");
5406 #else
5407   const XML_Char *expected = XCS("\xe0\xb8\x84\xe0\xb8\x88: \n");
5408 #endif
5409   CharData storage;
5410 
5411   CharData_Init(&storage);
5412   XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5413   XML_SetUserData(g_parser, &storage);
5414   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5415       == XML_STATUS_ERROR)
5416     xml_failure(g_parser);
5417   CharData_CheckXMLChars(&storage, expected);
5418 }
5419 END_TEST
5420 
5421 /* Test that comments can be picked up and translated */
5422 static void XMLCALL
accumulate_comment(void * userData,const XML_Char * data)5423 accumulate_comment(void *userData, const XML_Char *data) {
5424   CharData *storage = (CharData *)userData;
5425 
5426   CharData_AppendXMLChars(storage, data, -1);
5427 }
5428 
START_TEST(test_utf16_be_comment)5429 START_TEST(test_utf16_be_comment) {
5430   const char text[] =
5431       /* <!-- Comment A --> */
5432       "\0<\0!\0-\0-\0 \0C\0o\0m\0m\0e\0n\0t\0 \0A\0 \0-\0-\0>\0\n"
5433       /* <doc/> */
5434       "\0<\0d\0o\0c\0/\0>";
5435   const XML_Char *expected = XCS(" Comment A ");
5436   CharData storage;
5437 
5438   CharData_Init(&storage);
5439   XML_SetCommentHandler(g_parser, accumulate_comment);
5440   XML_SetUserData(g_parser, &storage);
5441   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5442       == XML_STATUS_ERROR)
5443     xml_failure(g_parser);
5444   CharData_CheckXMLChars(&storage, expected);
5445 }
5446 END_TEST
5447 
START_TEST(test_utf16_le_comment)5448 START_TEST(test_utf16_le_comment) {
5449   const char text[] =
5450       /* <!-- Comment B --> */
5451       "<\0!\0-\0-\0 \0C\0o\0m\0m\0e\0n\0t\0 \0B\0 \0-\0-\0>\0\n\0"
5452       /* <doc/> */
5453       "<\0d\0o\0c\0/\0>\0";
5454   const XML_Char *expected = XCS(" Comment B ");
5455   CharData storage;
5456 
5457   CharData_Init(&storage);
5458   XML_SetCommentHandler(g_parser, accumulate_comment);
5459   XML_SetUserData(g_parser, &storage);
5460   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5461       == XML_STATUS_ERROR)
5462     xml_failure(g_parser);
5463   CharData_CheckXMLChars(&storage, expected);
5464 }
5465 END_TEST
5466 
5467 /* Test that the unknown encoding handler with map entries that expect
5468  * conversion but no conversion function is faulted
5469  */
5470 static int XMLCALL
failing_converter(void * data,const char * s)5471 failing_converter(void *data, const char *s) {
5472   UNUSED_P(data);
5473   UNUSED_P(s);
5474   /* Always claim to have failed */
5475   return -1;
5476 }
5477 
5478 static int XMLCALL
prefix_converter(void * data,const char * s)5479 prefix_converter(void *data, const char *s) {
5480   UNUSED_P(data);
5481   /* If the first byte is 0xff, raise an error */
5482   if (s[0] == (char)-1)
5483     return -1;
5484   /* Just add the low bits of the first byte to the second */
5485   return (s[1] + (s[0] & 0x7f)) & 0x01ff;
5486 }
5487 
5488 static int XMLCALL
MiscEncodingHandler(void * data,const XML_Char * encoding,XML_Encoding * info)5489 MiscEncodingHandler(void *data, const XML_Char *encoding, XML_Encoding *info) {
5490   int i;
5491   int high_map = -2; /* Assume a 2-byte sequence */
5492 
5493   if (! xcstrcmp(encoding, XCS("invalid-9"))
5494       || ! xcstrcmp(encoding, XCS("ascii-like"))
5495       || ! xcstrcmp(encoding, XCS("invalid-len"))
5496       || ! xcstrcmp(encoding, XCS("invalid-a"))
5497       || ! xcstrcmp(encoding, XCS("invalid-surrogate"))
5498       || ! xcstrcmp(encoding, XCS("invalid-high")))
5499     high_map = -1;
5500 
5501   for (i = 0; i < 128; ++i)
5502     info->map[i] = i;
5503   for (; i < 256; ++i)
5504     info->map[i] = high_map;
5505 
5506   /* If required, put an invalid value in the ASCII entries */
5507   if (! xcstrcmp(encoding, XCS("invalid-9")))
5508     info->map[9] = 5;
5509   /* If required, have a top-bit set character starts a 5-byte sequence */
5510   if (! xcstrcmp(encoding, XCS("invalid-len")))
5511     info->map[0x81] = -5;
5512   /* If required, make a top-bit set character a valid ASCII character */
5513   if (! xcstrcmp(encoding, XCS("invalid-a")))
5514     info->map[0x82] = 'a';
5515   /* If required, give a top-bit set character a forbidden value,
5516    * what would otherwise be the first of a surrogate pair.
5517    */
5518   if (! xcstrcmp(encoding, XCS("invalid-surrogate")))
5519     info->map[0x83] = 0xd801;
5520   /* If required, give a top-bit set character too high a value */
5521   if (! xcstrcmp(encoding, XCS("invalid-high")))
5522     info->map[0x84] = 0x010101;
5523 
5524   info->data = data;
5525   info->release = NULL;
5526   if (! xcstrcmp(encoding, XCS("failing-conv")))
5527     info->convert = failing_converter;
5528   else if (! xcstrcmp(encoding, XCS("prefix-conv")))
5529     info->convert = prefix_converter;
5530   else
5531     info->convert = NULL;
5532   return XML_STATUS_OK;
5533 }
5534 
START_TEST(test_missing_encoding_conversion_fn)5535 START_TEST(test_missing_encoding_conversion_fn) {
5536   const char *text = "<?xml version='1.0' encoding='no-conv'?>\n"
5537                      "<doc>\x81</doc>";
5538 
5539   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5540   /* MiscEncodingHandler sets up an encoding with every top-bit-set
5541    * character introducing a two-byte sequence.  For this, it
5542    * requires a convert function.  The above function call doesn't
5543    * pass one through, so when BadEncodingHandler actually gets
5544    * called it should supply an invalid encoding.
5545    */
5546   expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5547                  "Encoding with missing convert() not faulted");
5548 }
5549 END_TEST
5550 
START_TEST(test_failing_encoding_conversion_fn)5551 START_TEST(test_failing_encoding_conversion_fn) {
5552   const char *text = "<?xml version='1.0' encoding='failing-conv'?>\n"
5553                      "<doc>\x81</doc>";
5554 
5555   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5556   /* BadEncodingHandler sets up an encoding with every top-bit-set
5557    * character introducing a two-byte sequence.  For this, it
5558    * requires a convert function.  The above function call passes
5559    * one that insists all possible sequences are invalid anyway.
5560    */
5561   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5562                  "Encoding with failing convert() not faulted");
5563 }
5564 END_TEST
5565 
5566 /* Test unknown encoding conversions */
START_TEST(test_unknown_encoding_success)5567 START_TEST(test_unknown_encoding_success) {
5568   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5569                      /* Equivalent to <eoc>Hello, world</eoc> */
5570                      "<\x81\x64\x80oc>Hello, world</\x81\x64\x80oc>";
5571 
5572   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5573   run_character_check(text, XCS("Hello, world"));
5574 }
5575 END_TEST
5576 
5577 /* Test bad name character in unknown encoding */
START_TEST(test_unknown_encoding_bad_name)5578 START_TEST(test_unknown_encoding_bad_name) {
5579   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5580                      "<\xff\x64oc>Hello, world</\xff\x64oc>";
5581 
5582   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5583   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5584                  "Bad name start in unknown encoding not faulted");
5585 }
5586 END_TEST
5587 
5588 /* Test bad mid-name character in unknown encoding */
START_TEST(test_unknown_encoding_bad_name_2)5589 START_TEST(test_unknown_encoding_bad_name_2) {
5590   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5591                      "<d\xffoc>Hello, world</d\xffoc>";
5592 
5593   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5594   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5595                  "Bad name in unknown encoding not faulted");
5596 }
5597 END_TEST
5598 
5599 /* Test element name that is long enough to fill the conversion buffer
5600  * in an unknown encoding, finishing with an encoded character.
5601  */
START_TEST(test_unknown_encoding_long_name_1)5602 START_TEST(test_unknown_encoding_long_name_1) {
5603   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5604                      "<abcdefghabcdefghabcdefghijkl\x80m\x80n\x80o\x80p>"
5605                      "Hi"
5606                      "</abcdefghabcdefghabcdefghijkl\x80m\x80n\x80o\x80p>";
5607   const XML_Char *expected = XCS("abcdefghabcdefghabcdefghijklmnop");
5608   CharData storage;
5609 
5610   CharData_Init(&storage);
5611   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5612   XML_SetStartElementHandler(g_parser, record_element_start_handler);
5613   XML_SetUserData(g_parser, &storage);
5614   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5615       == XML_STATUS_ERROR)
5616     xml_failure(g_parser);
5617   CharData_CheckXMLChars(&storage, expected);
5618 }
5619 END_TEST
5620 
5621 /* Test element name that is long enough to fill the conversion buffer
5622  * in an unknown encoding, finishing with an simple character.
5623  */
START_TEST(test_unknown_encoding_long_name_2)5624 START_TEST(test_unknown_encoding_long_name_2) {
5625   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5626                      "<abcdefghabcdefghabcdefghijklmnop>"
5627                      "Hi"
5628                      "</abcdefghabcdefghabcdefghijklmnop>";
5629   const XML_Char *expected = XCS("abcdefghabcdefghabcdefghijklmnop");
5630   CharData storage;
5631 
5632   CharData_Init(&storage);
5633   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5634   XML_SetStartElementHandler(g_parser, record_element_start_handler);
5635   XML_SetUserData(g_parser, &storage);
5636   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5637       == XML_STATUS_ERROR)
5638     xml_failure(g_parser);
5639   CharData_CheckXMLChars(&storage, expected);
5640 }
5641 END_TEST
5642 
START_TEST(test_invalid_unknown_encoding)5643 START_TEST(test_invalid_unknown_encoding) {
5644   const char *text = "<?xml version='1.0' encoding='invalid-9'?>\n"
5645                      "<doc>Hello world</doc>";
5646 
5647   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5648   expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5649                  "Invalid unknown encoding not faulted");
5650 }
5651 END_TEST
5652 
START_TEST(test_unknown_ascii_encoding_ok)5653 START_TEST(test_unknown_ascii_encoding_ok) {
5654   const char *text = "<?xml version='1.0' encoding='ascii-like'?>\n"
5655                      "<doc>Hello, world</doc>";
5656 
5657   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5658   run_character_check(text, XCS("Hello, world"));
5659 }
5660 END_TEST
5661 
START_TEST(test_unknown_ascii_encoding_fail)5662 START_TEST(test_unknown_ascii_encoding_fail) {
5663   const char *text = "<?xml version='1.0' encoding='ascii-like'?>\n"
5664                      "<doc>Hello, \x80 world</doc>";
5665 
5666   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5667   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5668                  "Invalid character not faulted");
5669 }
5670 END_TEST
5671 
START_TEST(test_unknown_encoding_invalid_length)5672 START_TEST(test_unknown_encoding_invalid_length) {
5673   const char *text = "<?xml version='1.0' encoding='invalid-len'?>\n"
5674                      "<doc>Hello, world</doc>";
5675 
5676   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5677   expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5678                  "Invalid unknown encoding not faulted");
5679 }
5680 END_TEST
5681 
START_TEST(test_unknown_encoding_invalid_topbit)5682 START_TEST(test_unknown_encoding_invalid_topbit) {
5683   const char *text = "<?xml version='1.0' encoding='invalid-a'?>\n"
5684                      "<doc>Hello, world</doc>";
5685 
5686   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5687   expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5688                  "Invalid unknown encoding not faulted");
5689 }
5690 END_TEST
5691 
START_TEST(test_unknown_encoding_invalid_surrogate)5692 START_TEST(test_unknown_encoding_invalid_surrogate) {
5693   const char *text = "<?xml version='1.0' encoding='invalid-surrogate'?>\n"
5694                      "<doc>Hello, \x82 world</doc>";
5695 
5696   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5697   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5698                  "Invalid unknown encoding not faulted");
5699 }
5700 END_TEST
5701 
START_TEST(test_unknown_encoding_invalid_high)5702 START_TEST(test_unknown_encoding_invalid_high) {
5703   const char *text = "<?xml version='1.0' encoding='invalid-high'?>\n"
5704                      "<doc>Hello, world</doc>";
5705 
5706   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5707   expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5708                  "Invalid unknown encoding not faulted");
5709 }
5710 END_TEST
5711 
START_TEST(test_unknown_encoding_invalid_attr_value)5712 START_TEST(test_unknown_encoding_invalid_attr_value) {
5713   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5714                      "<doc attr='\xff\x30'/>";
5715 
5716   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5717   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5718                  "Invalid attribute valid not faulted");
5719 }
5720 END_TEST
5721 
5722 /* Test an external entity parser set to use latin-1 detects UTF-16
5723  * BOMs correctly.
5724  */
5725 enum ee_parse_flags { EE_PARSE_NONE = 0x00, EE_PARSE_FULL_BUFFER = 0x01 };
5726 
5727 typedef struct ExtTest2 {
5728   const char *parse_text;
5729   int parse_len;
5730   const XML_Char *encoding;
5731   CharData *storage;
5732   enum ee_parse_flags flags;
5733 } ExtTest2;
5734 
5735 static int XMLCALL
external_entity_loader2(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)5736 external_entity_loader2(XML_Parser parser, const XML_Char *context,
5737                         const XML_Char *base, const XML_Char *systemId,
5738                         const XML_Char *publicId) {
5739   ExtTest2 *test_data = (ExtTest2 *)XML_GetUserData(parser);
5740   XML_Parser extparser;
5741 
5742   UNUSED_P(base);
5743   UNUSED_P(systemId);
5744   UNUSED_P(publicId);
5745   extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
5746   if (extparser == NULL)
5747     fail("Coulr not create external entity parser");
5748   if (test_data->encoding != NULL) {
5749     if (! XML_SetEncoding(extparser, test_data->encoding))
5750       fail("XML_SetEncoding() ignored for external entity");
5751   }
5752   if (test_data->flags & EE_PARSE_FULL_BUFFER) {
5753     if (XML_Parse(extparser, test_data->parse_text, test_data->parse_len,
5754                   XML_TRUE)
5755         == XML_STATUS_ERROR) {
5756       xml_failure(extparser);
5757     }
5758   } else if (_XML_Parse_SINGLE_BYTES(extparser, test_data->parse_text,
5759                                      test_data->parse_len, XML_TRUE)
5760              == XML_STATUS_ERROR) {
5761     xml_failure(extparser);
5762   }
5763 
5764   XML_ParserFree(extparser);
5765   return XML_STATUS_OK;
5766 }
5767 
5768 /* Test that UTF-16 BOM does not select UTF-16 given explicit encoding */
5769 static void XMLCALL
ext2_accumulate_characters(void * userData,const XML_Char * s,int len)5770 ext2_accumulate_characters(void *userData, const XML_Char *s, int len) {
5771   ExtTest2 *test_data = (ExtTest2 *)userData;
5772   accumulate_characters(test_data->storage, s, len);
5773 }
5774 
START_TEST(test_ext_entity_latin1_utf16le_bom)5775 START_TEST(test_ext_entity_latin1_utf16le_bom) {
5776   const char *text = "<!DOCTYPE doc [\n"
5777                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5778                      "]>\n"
5779                      "<doc>&en;</doc>";
5780   ExtTest2 test_data
5781       = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */
5782          /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn,
5783           *   0x4c = L and 0x20 is a space
5784           */
5785          "\xff\xfe\x4c\x20", 4, XCS("iso-8859-1"), NULL, EE_PARSE_NONE};
5786 #ifdef XML_UNICODE
5787   const XML_Char *expected = XCS("\x00ff\x00feL ");
5788 #else
5789   /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */
5790   const XML_Char *expected = XCS("\xc3\xbf\xc3\xbeL ");
5791 #endif
5792   CharData storage;
5793 
5794   CharData_Init(&storage);
5795   test_data.storage = &storage;
5796   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5797   XML_SetUserData(g_parser, &test_data);
5798   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5799   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5800       == XML_STATUS_ERROR)
5801     xml_failure(g_parser);
5802   CharData_CheckXMLChars(&storage, expected);
5803 }
5804 END_TEST
5805 
START_TEST(test_ext_entity_latin1_utf16be_bom)5806 START_TEST(test_ext_entity_latin1_utf16be_bom) {
5807   const char *text = "<!DOCTYPE doc [\n"
5808                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5809                      "]>\n"
5810                      "<doc>&en;</doc>";
5811   ExtTest2 test_data
5812       = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */
5813          /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn,
5814           *   0x4c = L and 0x20 is a space
5815           */
5816          "\xfe\xff\x20\x4c", 4, XCS("iso-8859-1"), NULL, EE_PARSE_NONE};
5817 #ifdef XML_UNICODE
5818   const XML_Char *expected = XCS("\x00fe\x00ff L");
5819 #else
5820   /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */
5821   const XML_Char *expected = XCS("\xc3\xbe\xc3\xbf L");
5822 #endif
5823   CharData storage;
5824 
5825   CharData_Init(&storage);
5826   test_data.storage = &storage;
5827   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5828   XML_SetUserData(g_parser, &test_data);
5829   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5830   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5831       == XML_STATUS_ERROR)
5832     xml_failure(g_parser);
5833   CharData_CheckXMLChars(&storage, expected);
5834 }
5835 END_TEST
5836 
5837 /* Parsing the full buffer rather than a byte at a time makes a
5838  * difference to the encoding scanning code, so repeat the above tests
5839  * without breaking them down by byte.
5840  */
START_TEST(test_ext_entity_latin1_utf16le_bom2)5841 START_TEST(test_ext_entity_latin1_utf16le_bom2) {
5842   const char *text = "<!DOCTYPE doc [\n"
5843                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5844                      "]>\n"
5845                      "<doc>&en;</doc>";
5846   ExtTest2 test_data
5847       = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */
5848          /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn,
5849           *   0x4c = L and 0x20 is a space
5850           */
5851          "\xff\xfe\x4c\x20", 4, XCS("iso-8859-1"), NULL, EE_PARSE_FULL_BUFFER};
5852 #ifdef XML_UNICODE
5853   const XML_Char *expected = XCS("\x00ff\x00feL ");
5854 #else
5855   /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */
5856   const XML_Char *expected = XCS("\xc3\xbf\xc3\xbeL ");
5857 #endif
5858   CharData storage;
5859 
5860   CharData_Init(&storage);
5861   test_data.storage = &storage;
5862   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5863   XML_SetUserData(g_parser, &test_data);
5864   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5865   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
5866       == XML_STATUS_ERROR)
5867     xml_failure(g_parser);
5868   CharData_CheckXMLChars(&storage, expected);
5869 }
5870 END_TEST
5871 
START_TEST(test_ext_entity_latin1_utf16be_bom2)5872 START_TEST(test_ext_entity_latin1_utf16be_bom2) {
5873   const char *text = "<!DOCTYPE doc [\n"
5874                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5875                      "]>\n"
5876                      "<doc>&en;</doc>";
5877   ExtTest2 test_data
5878       = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */
5879          /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn,
5880           *   0x4c = L and 0x20 is a space
5881           */
5882          "\xfe\xff\x20\x4c", 4, XCS("iso-8859-1"), NULL, EE_PARSE_FULL_BUFFER};
5883 #ifdef XML_UNICODE
5884   const XML_Char *expected = XCS("\x00fe\x00ff L");
5885 #else
5886   /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */
5887   const XML_Char *expected = "\xc3\xbe\xc3\xbf L";
5888 #endif
5889   CharData storage;
5890 
5891   CharData_Init(&storage);
5892   test_data.storage = &storage;
5893   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5894   XML_SetUserData(g_parser, &test_data);
5895   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5896   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
5897       == XML_STATUS_ERROR)
5898     xml_failure(g_parser);
5899   CharData_CheckXMLChars(&storage, expected);
5900 }
5901 END_TEST
5902 
5903 /* Test little-endian UTF-16 given an explicit big-endian encoding */
START_TEST(test_ext_entity_utf16_be)5904 START_TEST(test_ext_entity_utf16_be) {
5905   const char *text = "<!DOCTYPE doc [\n"
5906                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5907                      "]>\n"
5908                      "<doc>&en;</doc>";
5909   ExtTest2 test_data
5910       = {"<\0e\0/\0>\0", 8, XCS("utf-16be"), NULL, EE_PARSE_NONE};
5911 #ifdef XML_UNICODE
5912   const XML_Char *expected = XCS("\x3c00\x6500\x2f00\x3e00");
5913 #else
5914   const XML_Char *expected = XCS("\xe3\xb0\x80"   /* U+3C00 */
5915                                  "\xe6\x94\x80"   /* U+6500 */
5916                                  "\xe2\xbc\x80"   /* U+2F00 */
5917                                  "\xe3\xb8\x80"); /* U+3E00 */
5918 #endif
5919   CharData storage;
5920 
5921   CharData_Init(&storage);
5922   test_data.storage = &storage;
5923   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5924   XML_SetUserData(g_parser, &test_data);
5925   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5926   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5927       == XML_STATUS_ERROR)
5928     xml_failure(g_parser);
5929   CharData_CheckXMLChars(&storage, expected);
5930 }
5931 END_TEST
5932 
5933 /* Test big-endian UTF-16 given an explicit little-endian encoding */
START_TEST(test_ext_entity_utf16_le)5934 START_TEST(test_ext_entity_utf16_le) {
5935   const char *text = "<!DOCTYPE doc [\n"
5936                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5937                      "]>\n"
5938                      "<doc>&en;</doc>";
5939   ExtTest2 test_data
5940       = {"\0<\0e\0/\0>", 8, XCS("utf-16le"), NULL, EE_PARSE_NONE};
5941 #ifdef XML_UNICODE
5942   const XML_Char *expected = XCS("\x3c00\x6500\x2f00\x3e00");
5943 #else
5944   const XML_Char *expected = XCS("\xe3\xb0\x80"   /* U+3C00 */
5945                                  "\xe6\x94\x80"   /* U+6500 */
5946                                  "\xe2\xbc\x80"   /* U+2F00 */
5947                                  "\xe3\xb8\x80"); /* U+3E00 */
5948 #endif
5949   CharData storage;
5950 
5951   CharData_Init(&storage);
5952   test_data.storage = &storage;
5953   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5954   XML_SetUserData(g_parser, &test_data);
5955   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5956   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5957       == XML_STATUS_ERROR)
5958     xml_failure(g_parser);
5959   CharData_CheckXMLChars(&storage, expected);
5960 }
5961 END_TEST
5962 
5963 /* Test little-endian UTF-16 given no explicit encoding.
5964  * The existing default encoding (UTF-8) is assumed to hold without a
5965  * BOM to contradict it, so the entity value will in fact provoke an
5966  * error because 0x00 is not a valid XML character.  We parse the
5967  * whole buffer in one go rather than feeding it in byte by byte to
5968  * exercise different code paths in the initial scanning routines.
5969  */
5970 typedef struct ExtFaults2 {
5971   const char *parse_text;
5972   int parse_len;
5973   const char *fail_text;
5974   const XML_Char *encoding;
5975   enum XML_Error error;
5976 } ExtFaults2;
5977 
5978 static int XMLCALL
external_entity_faulter2(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)5979 external_entity_faulter2(XML_Parser parser, const XML_Char *context,
5980                          const XML_Char *base, const XML_Char *systemId,
5981                          const XML_Char *publicId) {
5982   ExtFaults2 *test_data = (ExtFaults2 *)XML_GetUserData(parser);
5983   XML_Parser extparser;
5984 
5985   UNUSED_P(base);
5986   UNUSED_P(systemId);
5987   UNUSED_P(publicId);
5988   extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
5989   if (extparser == NULL)
5990     fail("Could not create external entity parser");
5991   if (test_data->encoding != NULL) {
5992     if (! XML_SetEncoding(extparser, test_data->encoding))
5993       fail("XML_SetEncoding() ignored for external entity");
5994   }
5995   if (XML_Parse(extparser, test_data->parse_text, test_data->parse_len,
5996                 XML_TRUE)
5997       != XML_STATUS_ERROR)
5998     fail(test_data->fail_text);
5999   if (XML_GetErrorCode(extparser) != test_data->error)
6000     xml_failure(extparser);
6001 
6002   XML_ParserFree(extparser);
6003   return XML_STATUS_ERROR;
6004 }
6005 
START_TEST(test_ext_entity_utf16_unknown)6006 START_TEST(test_ext_entity_utf16_unknown) {
6007   const char *text = "<!DOCTYPE doc [\n"
6008                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
6009                      "]>\n"
6010                      "<doc>&en;</doc>";
6011   ExtFaults2 test_data
6012       = {"a\0b\0c\0", 6, "Invalid character in entity not faulted", NULL,
6013          XML_ERROR_INVALID_TOKEN};
6014 
6015   XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter2);
6016   XML_SetUserData(g_parser, &test_data);
6017   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
6018                  "Invalid character should not have been accepted");
6019 }
6020 END_TEST
6021 
6022 /* Test not-quite-UTF-8 BOM (0xEF 0xBB 0xBF) */
START_TEST(test_ext_entity_utf8_non_bom)6023 START_TEST(test_ext_entity_utf8_non_bom) {
6024   const char *text = "<!DOCTYPE doc [\n"
6025                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
6026                      "]>\n"
6027                      "<doc>&en;</doc>";
6028   ExtTest2 test_data
6029       = {"\xef\xbb\x80", /* Arabic letter DAD medial form, U+FEC0 */
6030          3, NULL, NULL, EE_PARSE_NONE};
6031 #ifdef XML_UNICODE
6032   const XML_Char *expected = XCS("\xfec0");
6033 #else
6034   const XML_Char *expected = XCS("\xef\xbb\x80");
6035 #endif
6036   CharData storage;
6037 
6038   CharData_Init(&storage);
6039   test_data.storage = &storage;
6040   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
6041   XML_SetUserData(g_parser, &test_data);
6042   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
6043   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6044       == XML_STATUS_ERROR)
6045     xml_failure(g_parser);
6046   CharData_CheckXMLChars(&storage, expected);
6047 }
6048 END_TEST
6049 
6050 /* Test that UTF-8 in a CDATA section is correctly passed through */
START_TEST(test_utf8_in_cdata_section)6051 START_TEST(test_utf8_in_cdata_section) {
6052   const char *text = "<doc><![CDATA[one \xc3\xa9 two]]></doc>";
6053 #ifdef XML_UNICODE
6054   const XML_Char *expected = XCS("one \x00e9 two");
6055 #else
6056   const XML_Char *expected = XCS("one \xc3\xa9 two");
6057 #endif
6058 
6059   run_character_check(text, expected);
6060 }
6061 END_TEST
6062 
6063 /* Test that little-endian UTF-16 in a CDATA section is handled */
START_TEST(test_utf8_in_cdata_section_2)6064 START_TEST(test_utf8_in_cdata_section_2) {
6065   const char *text = "<doc><![CDATA[\xc3\xa9]\xc3\xa9two]]></doc>";
6066 #ifdef XML_UNICODE
6067   const XML_Char *expected = XCS("\x00e9]\x00e9two");
6068 #else
6069   const XML_Char *expected = XCS("\xc3\xa9]\xc3\xa9two");
6070 #endif
6071 
6072   run_character_check(text, expected);
6073 }
6074 END_TEST
6075 
START_TEST(test_utf8_in_start_tags)6076 START_TEST(test_utf8_in_start_tags) {
6077   struct test_case {
6078     bool goodName;
6079     bool goodNameStart;
6080     const char *tagName;
6081   };
6082 
6083   // The idea with the tests below is this:
6084   // We want to cover 1-, 2- and 3-byte sequences, 4-byte sequences
6085   // go to isNever and are hence not a concern.
6086   //
6087   // We start with a character that is a valid name character
6088   // (or even name-start character, see XML 1.0r4 spec) and then we flip
6089   // single bits at places where (1) the result leaves the UTF-8 encoding space
6090   // and (2) we stay in the same n-byte sequence family.
6091   //
6092   // The flipped bits are highlighted in angle brackets in comments,
6093   // e.g. "[<1>011 1001]" means we had [0011 1001] but we now flipped
6094   // the most significant bit to 1 to leave UTF-8 encoding space.
6095   struct test_case cases[] = {
6096       // 1-byte UTF-8: [0xxx xxxx]
6097       {true, true, "\x3A"},   // [0011 1010] = ASCII colon ':'
6098       {false, false, "\xBA"}, // [<1>011 1010]
6099       {true, false, "\x39"},  // [0011 1001] = ASCII nine '9'
6100       {false, false, "\xB9"}, // [<1>011 1001]
6101 
6102       // 2-byte UTF-8: [110x xxxx] [10xx xxxx]
6103       {true, true, "\xDB\xA5"},   // [1101 1011] [1010 0101] =
6104                                   // Arabic small waw U+06E5
6105       {false, false, "\x9B\xA5"}, // [1<0>01 1011] [1010 0101]
6106       {false, false, "\xDB\x25"}, // [1101 1011] [<0>010 0101]
6107       {false, false, "\xDB\xE5"}, // [1101 1011] [1<1>10 0101]
6108       {true, false, "\xCC\x81"},  // [1100 1100] [1000 0001] =
6109                                   // combining char U+0301
6110       {false, false, "\x8C\x81"}, // [1<0>00 1100] [1000 0001]
6111       {false, false, "\xCC\x01"}, // [1100 1100] [<0>000 0001]
6112       {false, false, "\xCC\xC1"}, // [1100 1100] [1<1>00 0001]
6113 
6114       // 3-byte UTF-8: [1110 xxxx] [10xx xxxx] [10xxxxxx]
6115       {true, true, "\xE0\xA4\x85"},   // [1110 0000] [1010 0100] [1000 0101] =
6116                                       // Devanagari Letter A U+0905
6117       {false, false, "\xA0\xA4\x85"}, // [1<0>10 0000] [1010 0100] [1000 0101]
6118       {false, false, "\xE0\x24\x85"}, // [1110 0000] [<0>010 0100] [1000 0101]
6119       {false, false, "\xE0\xE4\x85"}, // [1110 0000] [1<1>10 0100] [1000 0101]
6120       {false, false, "\xE0\xA4\x05"}, // [1110 0000] [1010 0100] [<0>000 0101]
6121       {false, false, "\xE0\xA4\xC5"}, // [1110 0000] [1010 0100] [1<1>00 0101]
6122       {true, false, "\xE0\xA4\x81"},  // [1110 0000] [1010 0100] [1000 0001] =
6123                                       // combining char U+0901
6124       {false, false, "\xA0\xA4\x81"}, // [1<0>10 0000] [1010 0100] [1000 0001]
6125       {false, false, "\xE0\x24\x81"}, // [1110 0000] [<0>010 0100] [1000 0001]
6126       {false, false, "\xE0\xE4\x81"}, // [1110 0000] [1<1>10 0100] [1000 0001]
6127       {false, false, "\xE0\xA4\x01"}, // [1110 0000] [1010 0100] [<0>000 0001]
6128       {false, false, "\xE0\xA4\xC1"}, // [1110 0000] [1010 0100] [1<1>00 0001]
6129   };
6130   const bool atNameStart[] = {true, false};
6131 
6132   size_t i = 0;
6133   char doc[1024];
6134   size_t failCount = 0;
6135 
6136   for (; i < sizeof(cases) / sizeof(cases[0]); i++) {
6137     size_t j = 0;
6138     for (; j < sizeof(atNameStart) / sizeof(atNameStart[0]); j++) {
6139       const bool expectedSuccess
6140           = atNameStart[j] ? cases[i].goodNameStart : cases[i].goodName;
6141       sprintf(doc, "<%s%s><!--", atNameStart[j] ? "" : "a", cases[i].tagName);
6142       XML_Parser parser = XML_ParserCreate(NULL);
6143 
6144       const enum XML_Status status
6145           = XML_Parse(parser, doc, (int)strlen(doc), /*isFinal=*/XML_FALSE);
6146 
6147       bool success = true;
6148       if ((status == XML_STATUS_OK) != expectedSuccess) {
6149         success = false;
6150       }
6151       if ((status == XML_STATUS_ERROR)
6152           && (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN)) {
6153         success = false;
6154       }
6155 
6156       if (! success) {
6157         fprintf(
6158             stderr,
6159             "FAIL case %2u (%sat name start, %u-byte sequence, error code %d)\n",
6160             (unsigned)i + 1u, atNameStart[j] ? "    " : "not ",
6161             (unsigned)strlen(cases[i].tagName), XML_GetErrorCode(parser));
6162         failCount++;
6163       }
6164 
6165       XML_ParserFree(parser);
6166     }
6167   }
6168 
6169   if (failCount > 0) {
6170     fail("UTF-8 regression detected");
6171   }
6172 }
6173 END_TEST
6174 
6175 /* Test trailing spaces in elements are accepted */
6176 static void XMLCALL
record_element_end_handler(void * userData,const XML_Char * name)6177 record_element_end_handler(void *userData, const XML_Char *name) {
6178   CharData *storage = (CharData *)userData;
6179 
6180   CharData_AppendXMLChars(storage, XCS("/"), 1);
6181   CharData_AppendXMLChars(storage, name, -1);
6182 }
6183 
START_TEST(test_trailing_spaces_in_elements)6184 START_TEST(test_trailing_spaces_in_elements) {
6185   const char *text = "<doc   >Hi</doc >";
6186   const XML_Char *expected = XCS("doc/doc");
6187   CharData storage;
6188 
6189   CharData_Init(&storage);
6190   XML_SetElementHandler(g_parser, record_element_start_handler,
6191                         record_element_end_handler);
6192   XML_SetUserData(g_parser, &storage);
6193   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6194       == XML_STATUS_ERROR)
6195     xml_failure(g_parser);
6196   CharData_CheckXMLChars(&storage, expected);
6197 }
6198 END_TEST
6199 
START_TEST(test_utf16_attribute)6200 START_TEST(test_utf16_attribute) {
6201   const char text[] =
6202       /* <d {KHO KHWAI}{CHO CHAN}='a'/>
6203        * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
6204        * and   {CHO CHAN}  = U+0E08 = 0xe0 0xb8 0x88 in UTF-8
6205        */
6206       "<\0d\0 \0\x04\x0e\x08\x0e=\0'\0a\0'\0/\0>\0";
6207   const XML_Char *expected = XCS("a");
6208   CharData storage;
6209 
6210   CharData_Init(&storage);
6211   XML_SetStartElementHandler(g_parser, accumulate_attribute);
6212   XML_SetUserData(g_parser, &storage);
6213   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6214       == XML_STATUS_ERROR)
6215     xml_failure(g_parser);
6216   CharData_CheckXMLChars(&storage, expected);
6217 }
6218 END_TEST
6219 
START_TEST(test_utf16_second_attr)6220 START_TEST(test_utf16_second_attr) {
6221   /* <d a='1' {KHO KHWAI}{CHO CHAN}='2'/>
6222    * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
6223    * and   {CHO CHAN}  = U+0E08 = 0xe0 0xb8 0x88 in UTF-8
6224    */
6225   const char text[] = "<\0d\0 \0a\0=\0'\0\x31\0'\0 \0"
6226                       "\x04\x0e\x08\x0e=\0'\0\x32\0'\0/\0>\0";
6227   const XML_Char *expected = XCS("1");
6228   CharData storage;
6229 
6230   CharData_Init(&storage);
6231   XML_SetStartElementHandler(g_parser, accumulate_attribute);
6232   XML_SetUserData(g_parser, &storage);
6233   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6234       == XML_STATUS_ERROR)
6235     xml_failure(g_parser);
6236   CharData_CheckXMLChars(&storage, expected);
6237 }
6238 END_TEST
6239 
START_TEST(test_attr_after_solidus)6240 START_TEST(test_attr_after_solidus) {
6241   const char *text = "<doc attr1='a' / attr2='b'>";
6242 
6243   expect_failure(text, XML_ERROR_INVALID_TOKEN, "Misplaced / not faulted");
6244 }
6245 END_TEST
6246 
6247 static void XMLCALL
accumulate_entity_decl(void * userData,const XML_Char * entityName,int is_parameter_entity,const XML_Char * value,int value_length,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId,const XML_Char * notationName)6248 accumulate_entity_decl(void *userData, const XML_Char *entityName,
6249                        int is_parameter_entity, const XML_Char *value,
6250                        int value_length, const XML_Char *base,
6251                        const XML_Char *systemId, const XML_Char *publicId,
6252                        const XML_Char *notationName) {
6253   CharData *storage = (CharData *)userData;
6254 
6255   UNUSED_P(is_parameter_entity);
6256   UNUSED_P(base);
6257   UNUSED_P(systemId);
6258   UNUSED_P(publicId);
6259   UNUSED_P(notationName);
6260   CharData_AppendXMLChars(storage, entityName, -1);
6261   CharData_AppendXMLChars(storage, XCS("="), 1);
6262   CharData_AppendXMLChars(storage, value, value_length);
6263   CharData_AppendXMLChars(storage, XCS("\n"), 1);
6264 }
6265 
START_TEST(test_utf16_pe)6266 START_TEST(test_utf16_pe) {
6267   /* <!DOCTYPE doc [
6268    * <!ENTITY % {KHO KHWAI}{CHO CHAN} '<!ELEMENT doc (#PCDATA)>'>
6269    * %{KHO KHWAI}{CHO CHAN};
6270    * ]>
6271    * <doc></doc>
6272    *
6273    * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
6274    * and   {CHO CHAN}  = U+0E08 = 0xe0 0xb8 0x88 in UTF-8
6275    */
6276   const char text[] = "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0\n"
6277                       "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \x0e\x04\x0e\x08\0 "
6278                       "\0'\0<\0!\0E\0L\0E\0M\0E\0N\0T\0 "
6279                       "\0d\0o\0c\0 \0(\0#\0P\0C\0D\0A\0T\0A\0)\0>\0'\0>\0\n"
6280                       "\0%\x0e\x04\x0e\x08\0;\0\n"
6281                       "\0]\0>\0\n"
6282                       "\0<\0d\0o\0c\0>\0<\0/\0d\0o\0c\0>";
6283 #ifdef XML_UNICODE
6284   const XML_Char *expected = XCS("\x0e04\x0e08=<!ELEMENT doc (#PCDATA)>\n");
6285 #else
6286   const XML_Char *expected
6287       = XCS("\xe0\xb8\x84\xe0\xb8\x88=<!ELEMENT doc (#PCDATA)>\n");
6288 #endif
6289   CharData storage;
6290 
6291   CharData_Init(&storage);
6292   XML_SetUserData(g_parser, &storage);
6293   XML_SetEntityDeclHandler(g_parser, accumulate_entity_decl);
6294   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6295       == XML_STATUS_ERROR)
6296     xml_failure(g_parser);
6297   CharData_CheckXMLChars(&storage, expected);
6298 }
6299 END_TEST
6300 
6301 /* Test that duff attribute description keywords are rejected */
START_TEST(test_bad_attr_desc_keyword)6302 START_TEST(test_bad_attr_desc_keyword) {
6303   const char *text = "<!DOCTYPE doc [\n"
6304                      "  <!ATTLIST doc attr CDATA #!IMPLIED>\n"
6305                      "]>\n"
6306                      "<doc />";
6307 
6308   expect_failure(text, XML_ERROR_INVALID_TOKEN,
6309                  "Bad keyword !IMPLIED not faulted");
6310 }
6311 END_TEST
6312 
6313 /* Test that an invalid attribute description keyword consisting of
6314  * UTF-16 characters with their top bytes non-zero are correctly
6315  * faulted
6316  */
START_TEST(test_bad_attr_desc_keyword_utf16)6317 START_TEST(test_bad_attr_desc_keyword_utf16) {
6318   /* <!DOCTYPE d [
6319    * <!ATTLIST d a CDATA #{KHO KHWAI}{CHO CHAN}>
6320    * ]><d/>
6321    *
6322    * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
6323    * and   {CHO CHAN}  = U+0E08 = 0xe0 0xb8 0x88 in UTF-8
6324    */
6325   const char text[]
6326       = "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n"
6327         "\0<\0!\0A\0T\0T\0L\0I\0S\0T\0 \0d\0 \0a\0 \0C\0D\0A\0T\0A\0 "
6328         "\0#\x0e\x04\x0e\x08\0>\0\n"
6329         "\0]\0>\0<\0d\0/\0>";
6330 
6331   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6332       != XML_STATUS_ERROR)
6333     fail("Invalid UTF16 attribute keyword not faulted");
6334   if (XML_GetErrorCode(g_parser) != XML_ERROR_SYNTAX)
6335     xml_failure(g_parser);
6336 }
6337 END_TEST
6338 
6339 /* Test that invalid syntax in a <!DOCTYPE> is rejected.  Do this
6340  * using prefix-encoding (see above) to trigger specific code paths
6341  */
START_TEST(test_bad_doctype)6342 START_TEST(test_bad_doctype) {
6343   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
6344                      "<!DOCTYPE doc [ \x80\x44 ]><doc/>";
6345 
6346   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
6347   expect_failure(text, XML_ERROR_SYNTAX,
6348                  "Invalid bytes in DOCTYPE not faulted");
6349 }
6350 END_TEST
6351 
START_TEST(test_bad_doctype_utf8)6352 START_TEST(test_bad_doctype_utf8) {
6353   const char *text = "<!DOCTYPE \xDB\x25"
6354                      "doc><doc/>"; // [1101 1011] [<0>010 0101]
6355   expect_failure(text, XML_ERROR_INVALID_TOKEN,
6356                  "Invalid UTF-8 in DOCTYPE not faulted");
6357 }
6358 END_TEST
6359 
START_TEST(test_bad_doctype_utf16)6360 START_TEST(test_bad_doctype_utf16) {
6361   const char text[] =
6362       /* <!DOCTYPE doc [ \x06f2 ]><doc/>
6363        *
6364        * U+06F2 = EXTENDED ARABIC-INDIC DIGIT TWO, a valid number
6365        * (name character) but not a valid letter (name start character)
6366        */
6367       "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0 "
6368       "\x06\xf2"
6369       "\0 \0]\0>\0<\0d\0o\0c\0/\0>";
6370 
6371   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6372       != XML_STATUS_ERROR)
6373     fail("Invalid bytes in DOCTYPE not faulted");
6374   if (XML_GetErrorCode(g_parser) != XML_ERROR_SYNTAX)
6375     xml_failure(g_parser);
6376 }
6377 END_TEST
6378 
START_TEST(test_bad_doctype_plus)6379 START_TEST(test_bad_doctype_plus) {
6380   const char *text = "<!DOCTYPE 1+ [ <!ENTITY foo 'bar'> ]>\n"
6381                      "<1+>&foo;</1+>";
6382 
6383   expect_failure(text, XML_ERROR_INVALID_TOKEN,
6384                  "'+' in document name not faulted");
6385 }
6386 END_TEST
6387 
START_TEST(test_bad_doctype_star)6388 START_TEST(test_bad_doctype_star) {
6389   const char *text = "<!DOCTYPE 1* [ <!ENTITY foo 'bar'> ]>\n"
6390                      "<1*>&foo;</1*>";
6391 
6392   expect_failure(text, XML_ERROR_INVALID_TOKEN,
6393                  "'*' in document name not faulted");
6394 }
6395 END_TEST
6396 
START_TEST(test_bad_doctype_query)6397 START_TEST(test_bad_doctype_query) {
6398   const char *text = "<!DOCTYPE 1? [ <!ENTITY foo 'bar'> ]>\n"
6399                      "<1?>&foo;</1?>";
6400 
6401   expect_failure(text, XML_ERROR_INVALID_TOKEN,
6402                  "'?' in document name not faulted");
6403 }
6404 END_TEST
6405 
START_TEST(test_unknown_encoding_bad_ignore)6406 START_TEST(test_unknown_encoding_bad_ignore) {
6407   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>"
6408                      "<!DOCTYPE doc SYSTEM 'foo'>"
6409                      "<doc><e>&entity;</e></doc>";
6410   ExtFaults fault = {"<![IGNORE[<!ELEMENT \xffG (#PCDATA)*>]]>",
6411                      "Invalid character not faulted", XCS("prefix-conv"),
6412                      XML_ERROR_INVALID_TOKEN};
6413 
6414   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
6415   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6416   XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
6417   XML_SetUserData(g_parser, &fault);
6418   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
6419                  "Bad IGNORE section with unknown encoding not failed");
6420 }
6421 END_TEST
6422 
START_TEST(test_entity_in_utf16_be_attr)6423 START_TEST(test_entity_in_utf16_be_attr) {
6424   const char text[] =
6425       /* <e a='&#228; &#x00E4;'></e> */
6426       "\0<\0e\0 \0a\0=\0'\0&\0#\0\x32\0\x32\0\x38\0;\0 "
6427       "\0&\0#\0x\0\x30\0\x30\0E\0\x34\0;\0'\0>\0<\0/\0e\0>";
6428 #ifdef XML_UNICODE
6429   const XML_Char *expected = XCS("\x00e4 \x00e4");
6430 #else
6431   const XML_Char *expected = XCS("\xc3\xa4 \xc3\xa4");
6432 #endif
6433   CharData storage;
6434 
6435   CharData_Init(&storage);
6436   XML_SetUserData(g_parser, &storage);
6437   XML_SetStartElementHandler(g_parser, accumulate_attribute);
6438   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6439       == XML_STATUS_ERROR)
6440     xml_failure(g_parser);
6441   CharData_CheckXMLChars(&storage, expected);
6442 }
6443 END_TEST
6444 
START_TEST(test_entity_in_utf16_le_attr)6445 START_TEST(test_entity_in_utf16_le_attr) {
6446   const char text[] =
6447       /* <e a='&#228; &#x00E4;'></e> */
6448       "<\0e\0 \0a\0=\0'\0&\0#\0\x32\0\x32\0\x38\0;\0 \0"
6449       "&\0#\0x\0\x30\0\x30\0E\0\x34\0;\0'\0>\0<\0/\0e\0>\0";
6450 #ifdef XML_UNICODE
6451   const XML_Char *expected = XCS("\x00e4 \x00e4");
6452 #else
6453   const XML_Char *expected = XCS("\xc3\xa4 \xc3\xa4");
6454 #endif
6455   CharData storage;
6456 
6457   CharData_Init(&storage);
6458   XML_SetUserData(g_parser, &storage);
6459   XML_SetStartElementHandler(g_parser, accumulate_attribute);
6460   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6461       == XML_STATUS_ERROR)
6462     xml_failure(g_parser);
6463   CharData_CheckXMLChars(&storage, expected);
6464 }
6465 END_TEST
6466 
START_TEST(test_entity_public_utf16_be)6467 START_TEST(test_entity_public_utf16_be) {
6468   const char text[] =
6469       /* <!DOCTYPE d [ */
6470       "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n"
6471       /* <!ENTITY % e PUBLIC 'foo' 'bar.ent'> */
6472       "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \0e\0 \0P\0U\0B\0L\0I\0C\0 "
6473       "\0'\0f\0o\0o\0'\0 \0'\0b\0a\0r\0.\0e\0n\0t\0'\0>\0\n"
6474       /* %e; */
6475       "\0%\0e\0;\0\n"
6476       /* ]> */
6477       "\0]\0>\0\n"
6478       /* <d>&j;</d> */
6479       "\0<\0d\0>\0&\0j\0;\0<\0/\0d\0>";
6480   ExtTest2 test_data = {/* <!ENTITY j 'baz'> */
6481                         "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0j\0 \0'\0b\0a\0z\0'\0>",
6482                         34, NULL, NULL, EE_PARSE_NONE};
6483   const XML_Char *expected = XCS("baz");
6484   CharData storage;
6485 
6486   CharData_Init(&storage);
6487   test_data.storage = &storage;
6488   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6489   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
6490   XML_SetUserData(g_parser, &test_data);
6491   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
6492   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6493       == XML_STATUS_ERROR)
6494     xml_failure(g_parser);
6495   CharData_CheckXMLChars(&storage, expected);
6496 }
6497 END_TEST
6498 
START_TEST(test_entity_public_utf16_le)6499 START_TEST(test_entity_public_utf16_le) {
6500   const char text[] =
6501       /* <!DOCTYPE d [ */
6502       "<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n\0"
6503       /* <!ENTITY % e PUBLIC 'foo' 'bar.ent'> */
6504       "<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \0e\0 \0P\0U\0B\0L\0I\0C\0 \0"
6505       "'\0f\0o\0o\0'\0 \0'\0b\0a\0r\0.\0e\0n\0t\0'\0>\0\n\0"
6506       /* %e; */
6507       "%\0e\0;\0\n\0"
6508       /* ]> */
6509       "]\0>\0\n\0"
6510       /* <d>&j;</d> */
6511       "<\0d\0>\0&\0j\0;\0<\0/\0d\0>\0";
6512   ExtTest2 test_data = {/* <!ENTITY j 'baz'> */
6513                         "<\0!\0E\0N\0T\0I\0T\0Y\0 \0j\0 \0'\0b\0a\0z\0'\0>\0",
6514                         34, NULL, NULL, EE_PARSE_NONE};
6515   const XML_Char *expected = XCS("baz");
6516   CharData storage;
6517 
6518   CharData_Init(&storage);
6519   test_data.storage = &storage;
6520   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6521   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
6522   XML_SetUserData(g_parser, &test_data);
6523   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
6524   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6525       == XML_STATUS_ERROR)
6526     xml_failure(g_parser);
6527   CharData_CheckXMLChars(&storage, expected);
6528 }
6529 END_TEST
6530 
6531 /* Test that a doctype with neither an internal nor external subset is
6532  * faulted
6533  */
START_TEST(test_short_doctype)6534 START_TEST(test_short_doctype) {
6535   const char *text = "<!DOCTYPE doc></doc>";
6536   expect_failure(text, XML_ERROR_INVALID_TOKEN,
6537                  "DOCTYPE without subset not rejected");
6538 }
6539 END_TEST
6540 
START_TEST(test_short_doctype_2)6541 START_TEST(test_short_doctype_2) {
6542   const char *text = "<!DOCTYPE doc PUBLIC></doc>";
6543   expect_failure(text, XML_ERROR_SYNTAX,
6544                  "DOCTYPE without Public ID not rejected");
6545 }
6546 END_TEST
6547 
START_TEST(test_short_doctype_3)6548 START_TEST(test_short_doctype_3) {
6549   const char *text = "<!DOCTYPE doc SYSTEM></doc>";
6550   expect_failure(text, XML_ERROR_SYNTAX,
6551                  "DOCTYPE without System ID not rejected");
6552 }
6553 END_TEST
6554 
START_TEST(test_long_doctype)6555 START_TEST(test_long_doctype) {
6556   const char *text = "<!DOCTYPE doc PUBLIC 'foo' 'bar' 'baz'></doc>";
6557   expect_failure(text, XML_ERROR_SYNTAX, "DOCTYPE with extra ID not rejected");
6558 }
6559 END_TEST
6560 
START_TEST(test_bad_entity)6561 START_TEST(test_bad_entity) {
6562   const char *text = "<!DOCTYPE doc [\n"
6563                      "  <!ENTITY foo PUBLIC>\n"
6564                      "]>\n"
6565                      "<doc/>";
6566   expect_failure(text, XML_ERROR_SYNTAX,
6567                  "ENTITY without Public ID is not rejected");
6568 }
6569 END_TEST
6570 
6571 /* Test unquoted value is faulted */
START_TEST(test_bad_entity_2)6572 START_TEST(test_bad_entity_2) {
6573   const char *text = "<!DOCTYPE doc [\n"
6574                      "  <!ENTITY % foo bar>\n"
6575                      "]>\n"
6576                      "<doc/>";
6577   expect_failure(text, XML_ERROR_SYNTAX,
6578                  "ENTITY without Public ID is not rejected");
6579 }
6580 END_TEST
6581 
START_TEST(test_bad_entity_3)6582 START_TEST(test_bad_entity_3) {
6583   const char *text = "<!DOCTYPE doc [\n"
6584                      "  <!ENTITY % foo PUBLIC>\n"
6585                      "]>\n"
6586                      "<doc/>";
6587   expect_failure(text, XML_ERROR_SYNTAX,
6588                  "Parameter ENTITY without Public ID is not rejected");
6589 }
6590 END_TEST
6591 
START_TEST(test_bad_entity_4)6592 START_TEST(test_bad_entity_4) {
6593   const char *text = "<!DOCTYPE doc [\n"
6594                      "  <!ENTITY % foo SYSTEM>\n"
6595                      "]>\n"
6596                      "<doc/>";
6597   expect_failure(text, XML_ERROR_SYNTAX,
6598                  "Parameter ENTITY without Public ID is not rejected");
6599 }
6600 END_TEST
6601 
START_TEST(test_bad_notation)6602 START_TEST(test_bad_notation) {
6603   const char *text = "<!DOCTYPE doc [\n"
6604                      "  <!NOTATION n SYSTEM>\n"
6605                      "]>\n"
6606                      "<doc/>";
6607   expect_failure(text, XML_ERROR_SYNTAX,
6608                  "Notation without System ID is not rejected");
6609 }
6610 END_TEST
6611 
6612 /* Test for issue #11, wrongly suppressed default handler */
6613 typedef struct default_check {
6614   const XML_Char *expected;
6615   const int expectedLen;
6616   XML_Bool seen;
6617 } DefaultCheck;
6618 
6619 static void XMLCALL
checking_default_handler(void * userData,const XML_Char * s,int len)6620 checking_default_handler(void *userData, const XML_Char *s, int len) {
6621   DefaultCheck *data = (DefaultCheck *)userData;
6622   int i;
6623 
6624   for (i = 0; data[i].expected != NULL; i++) {
6625     if (data[i].expectedLen == len
6626         && ! memcmp(data[i].expected, s, len * sizeof(XML_Char))) {
6627       data[i].seen = XML_TRUE;
6628       break;
6629     }
6630   }
6631 }
6632 
START_TEST(test_default_doctype_handler)6633 START_TEST(test_default_doctype_handler) {
6634   const char *text = "<!DOCTYPE doc PUBLIC 'pubname' 'test.dtd' [\n"
6635                      "  <!ENTITY foo 'bar'>\n"
6636                      "]>\n"
6637                      "<doc>&foo;</doc>";
6638   DefaultCheck test_data[] = {{XCS("'pubname'"), 9, XML_FALSE},
6639                               {XCS("'test.dtd'"), 10, XML_FALSE},
6640                               {NULL, 0, XML_FALSE}};
6641   int i;
6642 
6643   XML_SetUserData(g_parser, &test_data);
6644   XML_SetDefaultHandler(g_parser, checking_default_handler);
6645   XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
6646   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6647       == XML_STATUS_ERROR)
6648     xml_failure(g_parser);
6649   for (i = 0; test_data[i].expected != NULL; i++)
6650     if (! test_data[i].seen)
6651       fail("Default handler not run for public !DOCTYPE");
6652 }
6653 END_TEST
6654 
START_TEST(test_empty_element_abort)6655 START_TEST(test_empty_element_abort) {
6656   const char *text = "<abort/>";
6657 
6658   XML_SetStartElementHandler(g_parser, start_element_suspender);
6659   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6660       != XML_STATUS_ERROR)
6661     fail("Expected to error on abort");
6662 }
6663 END_TEST
6664 
6665 /*
6666  * Namespaces tests.
6667  */
6668 
6669 static void
namespace_setup(void)6670 namespace_setup(void) {
6671   g_parser = XML_ParserCreateNS(NULL, XCS(' '));
6672   if (g_parser == NULL)
6673     fail("Parser not created.");
6674 }
6675 
6676 static void
namespace_teardown(void)6677 namespace_teardown(void) {
6678   basic_teardown();
6679 }
6680 
6681 /* Check that an element name and attribute name match the expected values.
6682    The expected values are passed as an array reference of string pointers
6683    provided as the userData argument; the first is the expected
6684    element name, and the second is the expected attribute name.
6685 */
6686 static int triplet_start_flag = XML_FALSE;
6687 static int triplet_end_flag = XML_FALSE;
6688 
6689 static void XMLCALL
triplet_start_checker(void * userData,const XML_Char * name,const XML_Char ** atts)6690 triplet_start_checker(void *userData, const XML_Char *name,
6691                       const XML_Char **atts) {
6692   XML_Char **elemstr = (XML_Char **)userData;
6693   char buffer[1024];
6694   if (xcstrcmp(elemstr[0], name) != 0) {
6695     sprintf(buffer, "unexpected start string: '%" XML_FMT_STR "'", name);
6696     fail(buffer);
6697   }
6698   if (xcstrcmp(elemstr[1], atts[0]) != 0) {
6699     sprintf(buffer, "unexpected attribute string: '%" XML_FMT_STR "'", atts[0]);
6700     fail(buffer);
6701   }
6702   triplet_start_flag = XML_TRUE;
6703 }
6704 
6705 /* Check that the element name passed to the end-element handler matches
6706    the expected value.  The expected value is passed as the first element
6707    in an array of strings passed as the userData argument.
6708 */
6709 static void XMLCALL
triplet_end_checker(void * userData,const XML_Char * name)6710 triplet_end_checker(void *userData, const XML_Char *name) {
6711   XML_Char **elemstr = (XML_Char **)userData;
6712   if (xcstrcmp(elemstr[0], name) != 0) {
6713     char buffer[1024];
6714     sprintf(buffer, "unexpected end string: '%" XML_FMT_STR "'", name);
6715     fail(buffer);
6716   }
6717   triplet_end_flag = XML_TRUE;
6718 }
6719 
START_TEST(test_return_ns_triplet)6720 START_TEST(test_return_ns_triplet) {
6721   const char *text = "<foo:e xmlns:foo='http://example.org/' bar:a='12'\n"
6722                      "       xmlns:bar='http://example.org/'>";
6723   const char *epilog = "</foo:e>";
6724   const XML_Char *elemstr[]
6725       = {XCS("http://example.org/ e foo"), XCS("http://example.org/ a bar")};
6726   XML_SetReturnNSTriplet(g_parser, XML_TRUE);
6727   XML_SetUserData(g_parser, (void *)elemstr);
6728   XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
6729   XML_SetNamespaceDeclHandler(g_parser, dummy_start_namespace_decl_handler,
6730                               dummy_end_namespace_decl_handler);
6731   triplet_start_flag = XML_FALSE;
6732   triplet_end_flag = XML_FALSE;
6733   dummy_handler_flags = 0;
6734   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
6735       == XML_STATUS_ERROR)
6736     xml_failure(g_parser);
6737   if (! triplet_start_flag)
6738     fail("triplet_start_checker not invoked");
6739   /* Check that unsetting "return triplets" fails while still parsing */
6740   XML_SetReturnNSTriplet(g_parser, XML_FALSE);
6741   if (_XML_Parse_SINGLE_BYTES(g_parser, epilog, (int)strlen(epilog), XML_TRUE)
6742       == XML_STATUS_ERROR)
6743     xml_failure(g_parser);
6744   if (! triplet_end_flag)
6745     fail("triplet_end_checker not invoked");
6746   if (dummy_handler_flags
6747       != (DUMMY_START_NS_DECL_HANDLER_FLAG | DUMMY_END_NS_DECL_HANDLER_FLAG))
6748     fail("Namespace handlers not called");
6749 }
6750 END_TEST
6751 
6752 static void XMLCALL
overwrite_start_checker(void * userData,const XML_Char * name,const XML_Char ** atts)6753 overwrite_start_checker(void *userData, const XML_Char *name,
6754                         const XML_Char **atts) {
6755   CharData *storage = (CharData *)userData;
6756   CharData_AppendXMLChars(storage, XCS("start "), 6);
6757   CharData_AppendXMLChars(storage, name, -1);
6758   while (*atts != NULL) {
6759     CharData_AppendXMLChars(storage, XCS("\nattribute "), 11);
6760     CharData_AppendXMLChars(storage, *atts, -1);
6761     atts += 2;
6762   }
6763   CharData_AppendXMLChars(storage, XCS("\n"), 1);
6764 }
6765 
6766 static void XMLCALL
overwrite_end_checker(void * userData,const XML_Char * name)6767 overwrite_end_checker(void *userData, const XML_Char *name) {
6768   CharData *storage = (CharData *)userData;
6769   CharData_AppendXMLChars(storage, XCS("end "), 4);
6770   CharData_AppendXMLChars(storage, name, -1);
6771   CharData_AppendXMLChars(storage, XCS("\n"), 1);
6772 }
6773 
6774 static void
run_ns_tagname_overwrite_test(const char * text,const XML_Char * result)6775 run_ns_tagname_overwrite_test(const char *text, const XML_Char *result) {
6776   CharData storage;
6777   CharData_Init(&storage);
6778   XML_SetUserData(g_parser, &storage);
6779   XML_SetElementHandler(g_parser, overwrite_start_checker,
6780                         overwrite_end_checker);
6781   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6782       == XML_STATUS_ERROR)
6783     xml_failure(g_parser);
6784   CharData_CheckXMLChars(&storage, result);
6785 }
6786 
6787 /* Regression test for SF bug #566334. */
START_TEST(test_ns_tagname_overwrite)6788 START_TEST(test_ns_tagname_overwrite) {
6789   const char *text = "<n:e xmlns:n='http://example.org/'>\n"
6790                      "  <n:f n:attr='foo'/>\n"
6791                      "  <n:g n:attr2='bar'/>\n"
6792                      "</n:e>";
6793   const XML_Char *result = XCS("start http://example.org/ e\n")
6794       XCS("start http://example.org/ f\n")
6795           XCS("attribute http://example.org/ attr\n")
6796               XCS("end http://example.org/ f\n")
6797                   XCS("start http://example.org/ g\n")
6798                       XCS("attribute http://example.org/ attr2\n")
6799                           XCS("end http://example.org/ g\n")
6800                               XCS("end http://example.org/ e\n");
6801   run_ns_tagname_overwrite_test(text, result);
6802 }
6803 END_TEST
6804 
6805 /* Regression test for SF bug #566334. */
START_TEST(test_ns_tagname_overwrite_triplet)6806 START_TEST(test_ns_tagname_overwrite_triplet) {
6807   const char *text = "<n:e xmlns:n='http://example.org/'>\n"
6808                      "  <n:f n:attr='foo'/>\n"
6809                      "  <n:g n:attr2='bar'/>\n"
6810                      "</n:e>";
6811   const XML_Char *result = XCS("start http://example.org/ e n\n")
6812       XCS("start http://example.org/ f n\n")
6813           XCS("attribute http://example.org/ attr n\n")
6814               XCS("end http://example.org/ f n\n")
6815                   XCS("start http://example.org/ g n\n")
6816                       XCS("attribute http://example.org/ attr2 n\n")
6817                           XCS("end http://example.org/ g n\n")
6818                               XCS("end http://example.org/ e n\n");
6819   XML_SetReturnNSTriplet(g_parser, XML_TRUE);
6820   run_ns_tagname_overwrite_test(text, result);
6821 }
6822 END_TEST
6823 
6824 /* Regression test for SF bug #620343. */
6825 static void XMLCALL
start_element_fail(void * userData,const XML_Char * name,const XML_Char ** atts)6826 start_element_fail(void *userData, const XML_Char *name,
6827                    const XML_Char **atts) {
6828   UNUSED_P(userData);
6829   UNUSED_P(name);
6830   UNUSED_P(atts);
6831 
6832   /* We should never get here. */
6833   fail("should never reach start_element_fail()");
6834 }
6835 
6836 static void XMLCALL
start_ns_clearing_start_element(void * userData,const XML_Char * prefix,const XML_Char * uri)6837 start_ns_clearing_start_element(void *userData, const XML_Char *prefix,
6838                                 const XML_Char *uri) {
6839   UNUSED_P(prefix);
6840   UNUSED_P(uri);
6841   XML_SetStartElementHandler((XML_Parser)userData, NULL);
6842 }
6843 
START_TEST(test_start_ns_clears_start_element)6844 START_TEST(test_start_ns_clears_start_element) {
6845   /* This needs to use separate start/end tags; using the empty tag
6846      syntax doesn't cause the problematic path through Expat to be
6847      taken.
6848   */
6849   const char *text = "<e xmlns='http://example.org/'></e>";
6850 
6851   XML_SetStartElementHandler(g_parser, start_element_fail);
6852   XML_SetStartNamespaceDeclHandler(g_parser, start_ns_clearing_start_element);
6853   XML_SetEndNamespaceDeclHandler(g_parser, dummy_end_namespace_decl_handler);
6854   XML_UseParserAsHandlerArg(g_parser);
6855   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6856       == XML_STATUS_ERROR)
6857     xml_failure(g_parser);
6858 }
6859 END_TEST
6860 
6861 /* Regression test for SF bug #616863. */
6862 static int XMLCALL
external_entity_handler(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)6863 external_entity_handler(XML_Parser parser, const XML_Char *context,
6864                         const XML_Char *base, const XML_Char *systemId,
6865                         const XML_Char *publicId) {
6866   intptr_t callno = 1 + (intptr_t)XML_GetUserData(parser);
6867   const char *text;
6868   XML_Parser p2;
6869 
6870   UNUSED_P(base);
6871   UNUSED_P(systemId);
6872   UNUSED_P(publicId);
6873   if (callno == 1)
6874     text = ("<!ELEMENT doc (e+)>\n"
6875             "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
6876             "<!ELEMENT e EMPTY>\n");
6877   else
6878     text = ("<?xml version='1.0' encoding='us-ascii'?>"
6879             "<e/>");
6880 
6881   XML_SetUserData(parser, (void *)callno);
6882   p2 = XML_ExternalEntityParserCreate(parser, context, NULL);
6883   if (_XML_Parse_SINGLE_BYTES(p2, text, (int)strlen(text), XML_TRUE)
6884       == XML_STATUS_ERROR) {
6885     xml_failure(p2);
6886     return XML_STATUS_ERROR;
6887   }
6888   XML_ParserFree(p2);
6889   return XML_STATUS_OK;
6890 }
6891 
START_TEST(test_default_ns_from_ext_subset_and_ext_ge)6892 START_TEST(test_default_ns_from_ext_subset_and_ext_ge) {
6893   const char *text = "<?xml version='1.0'?>\n"
6894                      "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n"
6895                      "  <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n"
6896                      "]>\n"
6897                      "<doc xmlns='http://example.org/ns1'>\n"
6898                      "&en;\n"
6899                      "</doc>";
6900 
6901   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6902   XML_SetExternalEntityRefHandler(g_parser, external_entity_handler);
6903   /* We actually need to set this handler to tickle this bug. */
6904   XML_SetStartElementHandler(g_parser, dummy_start_element);
6905   XML_SetUserData(g_parser, NULL);
6906   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6907       == XML_STATUS_ERROR)
6908     xml_failure(g_parser);
6909 }
6910 END_TEST
6911 
6912 /* Regression test #1 for SF bug #673791. */
START_TEST(test_ns_prefix_with_empty_uri_1)6913 START_TEST(test_ns_prefix_with_empty_uri_1) {
6914   const char *text = "<doc xmlns:prefix='http://example.org/'>\n"
6915                      "  <e xmlns:prefix=''/>\n"
6916                      "</doc>";
6917 
6918   expect_failure(text, XML_ERROR_UNDECLARING_PREFIX,
6919                  "Did not report re-setting namespace"
6920                  " URI with prefix to ''.");
6921 }
6922 END_TEST
6923 
6924 /* Regression test #2 for SF bug #673791. */
START_TEST(test_ns_prefix_with_empty_uri_2)6925 START_TEST(test_ns_prefix_with_empty_uri_2) {
6926   const char *text = "<?xml version='1.0'?>\n"
6927                      "<docelem xmlns:pre=''/>";
6928 
6929   expect_failure(text, XML_ERROR_UNDECLARING_PREFIX,
6930                  "Did not report setting namespace URI with prefix to ''.");
6931 }
6932 END_TEST
6933 
6934 /* Regression test #3 for SF bug #673791. */
START_TEST(test_ns_prefix_with_empty_uri_3)6935 START_TEST(test_ns_prefix_with_empty_uri_3) {
6936   const char *text = "<!DOCTYPE doc [\n"
6937                      "  <!ELEMENT doc EMPTY>\n"
6938                      "  <!ATTLIST doc\n"
6939                      "    xmlns:prefix CDATA ''>\n"
6940                      "]>\n"
6941                      "<doc/>";
6942 
6943   expect_failure(text, XML_ERROR_UNDECLARING_PREFIX,
6944                  "Didn't report attr default setting NS w/ prefix to ''.");
6945 }
6946 END_TEST
6947 
6948 /* Regression test #4 for SF bug #673791. */
START_TEST(test_ns_prefix_with_empty_uri_4)6949 START_TEST(test_ns_prefix_with_empty_uri_4) {
6950   const char *text = "<!DOCTYPE doc [\n"
6951                      "  <!ELEMENT prefix:doc EMPTY>\n"
6952                      "  <!ATTLIST prefix:doc\n"
6953                      "    xmlns:prefix CDATA 'http://example.org/'>\n"
6954                      "]>\n"
6955                      "<prefix:doc/>";
6956   /* Packaged info expected by the end element handler;
6957      the weird structuring lets us re-use the triplet_end_checker()
6958      function also used for another test. */
6959   const XML_Char *elemstr[] = {XCS("http://example.org/ doc prefix")};
6960   XML_SetReturnNSTriplet(g_parser, XML_TRUE);
6961   XML_SetUserData(g_parser, (void *)elemstr);
6962   XML_SetEndElementHandler(g_parser, triplet_end_checker);
6963   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6964       == XML_STATUS_ERROR)
6965     xml_failure(g_parser);
6966 }
6967 END_TEST
6968 
6969 /* Test with non-xmlns prefix */
START_TEST(test_ns_unbound_prefix)6970 START_TEST(test_ns_unbound_prefix) {
6971   const char *text = "<!DOCTYPE doc [\n"
6972                      "  <!ELEMENT prefix:doc EMPTY>\n"
6973                      "  <!ATTLIST prefix:doc\n"
6974                      "    notxmlns:prefix CDATA 'http://example.org/'>\n"
6975                      "]>\n"
6976                      "<prefix:doc/>";
6977 
6978   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6979       != XML_STATUS_ERROR)
6980     fail("Unbound prefix incorrectly passed");
6981   if (XML_GetErrorCode(g_parser) != XML_ERROR_UNBOUND_PREFIX)
6982     xml_failure(g_parser);
6983 }
6984 END_TEST
6985 
START_TEST(test_ns_default_with_empty_uri)6986 START_TEST(test_ns_default_with_empty_uri) {
6987   const char *text = "<doc xmlns='http://example.org/'>\n"
6988                      "  <e xmlns=''/>\n"
6989                      "</doc>";
6990   /* Add some handlers to exercise extra code paths */
6991   XML_SetStartNamespaceDeclHandler(g_parser,
6992                                    dummy_start_namespace_decl_handler);
6993   XML_SetEndNamespaceDeclHandler(g_parser, dummy_end_namespace_decl_handler);
6994   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6995       == XML_STATUS_ERROR)
6996     xml_failure(g_parser);
6997 }
6998 END_TEST
6999 
7000 /* Regression test for SF bug #692964: two prefixes for one namespace. */
START_TEST(test_ns_duplicate_attrs_diff_prefixes)7001 START_TEST(test_ns_duplicate_attrs_diff_prefixes) {
7002   const char *text = "<doc xmlns:a='http://example.org/a'\n"
7003                      "     xmlns:b='http://example.org/a'\n"
7004                      "     a:a='v' b:a='v' />";
7005   expect_failure(text, XML_ERROR_DUPLICATE_ATTRIBUTE,
7006                  "did not report multiple attributes with same URI+name");
7007 }
7008 END_TEST
7009 
START_TEST(test_ns_duplicate_hashes)7010 START_TEST(test_ns_duplicate_hashes) {
7011   /* The hash of an attribute is calculated as the hash of its URI
7012    * concatenated with a space followed by its name (after the
7013    * colon).  We wish to generate attributes with the same hash
7014    * value modulo the attribute table size so that we can check that
7015    * the attribute hash table works correctly.  The attribute hash
7016    * table size will be the smallest power of two greater than the
7017    * number of attributes, but at least eight.  There is
7018    * unfortunately no programmatic way of getting the hash or the
7019    * table size at user level, but the test code coverage percentage
7020    * will drop if the hashes cease to point to the same row.
7021    *
7022    * The cunning plan is to have few enough attributes to have a
7023    * reliable table size of 8, and have the single letter attribute
7024    * names be 8 characters apart, producing a hash which will be the
7025    * same modulo 8.
7026    */
7027   const char *text = "<doc xmlns:a='http://example.org/a'\n"
7028                      "     a:a='v' a:i='w' />";
7029   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7030       == XML_STATUS_ERROR)
7031     xml_failure(g_parser);
7032 }
7033 END_TEST
7034 
7035 /* Regression test for SF bug #695401: unbound prefix. */
START_TEST(test_ns_unbound_prefix_on_attribute)7036 START_TEST(test_ns_unbound_prefix_on_attribute) {
7037   const char *text = "<doc a:attr=''/>";
7038   expect_failure(text, XML_ERROR_UNBOUND_PREFIX,
7039                  "did not report unbound prefix on attribute");
7040 }
7041 END_TEST
7042 
7043 /* Regression test for SF bug #695401: unbound prefix. */
START_TEST(test_ns_unbound_prefix_on_element)7044 START_TEST(test_ns_unbound_prefix_on_element) {
7045   const char *text = "<a:doc/>";
7046   expect_failure(text, XML_ERROR_UNBOUND_PREFIX,
7047                  "did not report unbound prefix on element");
7048 }
7049 END_TEST
7050 
7051 /* Test that the parsing status is correctly reset by XML_ParserReset().
7052  * We usE test_return_ns_triplet() for our example parse to improve
7053  * coverage of tidying up code executed.
7054  */
START_TEST(test_ns_parser_reset)7055 START_TEST(test_ns_parser_reset) {
7056   XML_ParsingStatus status;
7057 
7058   XML_GetParsingStatus(g_parser, &status);
7059   if (status.parsing != XML_INITIALIZED)
7060     fail("parsing status doesn't start INITIALIZED");
7061   test_return_ns_triplet();
7062   XML_GetParsingStatus(g_parser, &status);
7063   if (status.parsing != XML_FINISHED)
7064     fail("parsing status doesn't end FINISHED");
7065   XML_ParserReset(g_parser, NULL);
7066   XML_GetParsingStatus(g_parser, &status);
7067   if (status.parsing != XML_INITIALIZED)
7068     fail("parsing status doesn't reset to INITIALIZED");
7069 }
7070 END_TEST
7071 
7072 /* Test that long element names with namespaces are handled correctly */
START_TEST(test_ns_long_element)7073 START_TEST(test_ns_long_element) {
7074   const char *text
7075       = "<foo:thisisalongenoughelementnametotriggerareallocation\n"
7076         " xmlns:foo='http://example.org/' bar:a='12'\n"
7077         " xmlns:bar='http://example.org/'>"
7078         "</foo:thisisalongenoughelementnametotriggerareallocation>";
7079   const XML_Char *elemstr[]
7080       = {XCS("http://example.org/")
7081              XCS(" thisisalongenoughelementnametotriggerareallocation foo"),
7082          XCS("http://example.org/ a bar")};
7083 
7084   XML_SetReturnNSTriplet(g_parser, XML_TRUE);
7085   XML_SetUserData(g_parser, (void *)elemstr);
7086   XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
7087   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7088       == XML_STATUS_ERROR)
7089     xml_failure(g_parser);
7090 }
7091 END_TEST
7092 
7093 /* Test mixed population of prefixed and unprefixed attributes */
START_TEST(test_ns_mixed_prefix_atts)7094 START_TEST(test_ns_mixed_prefix_atts) {
7095   const char *text = "<e a='12' bar:b='13'\n"
7096                      " xmlns:bar='http://example.org/'>"
7097                      "</e>";
7098 
7099   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7100       == XML_STATUS_ERROR)
7101     xml_failure(g_parser);
7102 }
7103 END_TEST
7104 
7105 /* Test having a long namespaced element name inside a short one.
7106  * This exercises some internal buffer reallocation that is shared
7107  * across elements with the same namespace URI.
7108  */
START_TEST(test_ns_extend_uri_buffer)7109 START_TEST(test_ns_extend_uri_buffer) {
7110   const char *text = "<foo:e xmlns:foo='http://example.org/'>"
7111                      " <foo:thisisalongenoughnametotriggerallocationaction"
7112                      "   foo:a='12' />"
7113                      "</foo:e>";
7114   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7115       == XML_STATUS_ERROR)
7116     xml_failure(g_parser);
7117 }
7118 END_TEST
7119 
7120 /* Test that xmlns is correctly rejected as an attribute in the xmlns
7121  * namespace, but not in other namespaces
7122  */
START_TEST(test_ns_reserved_attributes)7123 START_TEST(test_ns_reserved_attributes) {
7124   const char *text1
7125       = "<foo:e xmlns:foo='http://example.org/' xmlns:xmlns='12' />";
7126   const char *text2
7127       = "<foo:e xmlns:foo='http://example.org/' foo:xmlns='12' />";
7128   expect_failure(text1, XML_ERROR_RESERVED_PREFIX_XMLNS,
7129                  "xmlns not rejected as an attribute");
7130   XML_ParserReset(g_parser, NULL);
7131   if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
7132       == XML_STATUS_ERROR)
7133     xml_failure(g_parser);
7134 }
7135 END_TEST
7136 
7137 /* Test more reserved attributes */
START_TEST(test_ns_reserved_attributes_2)7138 START_TEST(test_ns_reserved_attributes_2) {
7139   const char *text1 = "<foo:e xmlns:foo='http://example.org/'"
7140                       "  xmlns:xml='http://example.org/' />";
7141   const char *text2
7142       = "<foo:e xmlns:foo='http://www.w3.org/XML/1998/namespace' />";
7143   const char *text3 = "<foo:e xmlns:foo='http://www.w3.org/2000/xmlns/' />";
7144 
7145   expect_failure(text1, XML_ERROR_RESERVED_PREFIX_XML,
7146                  "xml not rejected as an attribute");
7147   XML_ParserReset(g_parser, NULL);
7148   expect_failure(text2, XML_ERROR_RESERVED_NAMESPACE_URI,
7149                  "Use of w3.org URL not faulted");
7150   XML_ParserReset(g_parser, NULL);
7151   expect_failure(text3, XML_ERROR_RESERVED_NAMESPACE_URI,
7152                  "Use of w3.org xmlns URL not faulted");
7153 }
7154 END_TEST
7155 
7156 /* Test string pool handling of namespace names of 2048 characters */
7157 /* Exercises a particular string pool growth path */
START_TEST(test_ns_extremely_long_prefix)7158 START_TEST(test_ns_extremely_long_prefix) {
7159   /* C99 compilers are only required to support 4095-character
7160    * strings, so the following needs to be split in two to be safe
7161    * for all compilers.
7162    */
7163   const char *text1
7164       = "<doc "
7165         /* 64 character on each line */
7166         /* ...gives a total length of 2048 */
7167         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7168         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7169         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7170         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7171         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7172         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7173         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7174         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7175         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7176         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7177         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7178         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7179         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7180         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7181         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7182         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7183         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7184         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7185         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7186         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7187         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7188         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7189         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7190         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7191         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7192         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7193         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7194         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7195         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7196         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7197         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7198         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7199         ":a='12'";
7200   const char *text2
7201       = " xmlns:"
7202         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7203         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7204         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7205         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7206         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7207         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7208         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7209         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7210         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7211         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7212         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7213         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7214         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7215         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7216         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7217         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7218         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7219         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7220         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7221         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7222         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7223         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7224         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7225         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7226         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7227         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7228         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7229         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7230         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7231         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7232         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7233         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7234         "='foo'\n>"
7235         "</doc>";
7236 
7237   if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
7238       == XML_STATUS_ERROR)
7239     xml_failure(g_parser);
7240   if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
7241       == XML_STATUS_ERROR)
7242     xml_failure(g_parser);
7243 }
7244 END_TEST
7245 
7246 /* Test unknown encoding handlers in namespace setup */
START_TEST(test_ns_unknown_encoding_success)7247 START_TEST(test_ns_unknown_encoding_success) {
7248   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
7249                      "<foo:e xmlns:foo='http://example.org/'>Hi</foo:e>";
7250 
7251   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
7252   run_character_check(text, XCS("Hi"));
7253 }
7254 END_TEST
7255 
7256 /* Test that too many colons are rejected */
START_TEST(test_ns_double_colon)7257 START_TEST(test_ns_double_colon) {
7258   const char *text = "<foo:e xmlns:foo='http://example.org/' foo:a:b='bar' />";
7259   const enum XML_Status status
7260       = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE);
7261 #ifdef XML_NS
7262   if ((status == XML_STATUS_OK)
7263       || (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)) {
7264     fail("Double colon in attribute name not faulted"
7265          " (despite active namespace support)");
7266   }
7267 #else
7268   if (status != XML_STATUS_OK) {
7269     fail("Double colon in attribute name faulted"
7270          " (despite inactive namespace support");
7271   }
7272 #endif
7273 }
7274 END_TEST
7275 
START_TEST(test_ns_double_colon_element)7276 START_TEST(test_ns_double_colon_element) {
7277   const char *text = "<foo:bar:e xmlns:foo='http://example.org/' />";
7278   const enum XML_Status status
7279       = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE);
7280 #ifdef XML_NS
7281   if ((status == XML_STATUS_OK)
7282       || (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)) {
7283     fail("Double colon in element name not faulted"
7284          " (despite active namespace support)");
7285   }
7286 #else
7287   if (status != XML_STATUS_OK) {
7288     fail("Double colon in element name faulted"
7289          " (despite inactive namespace support");
7290   }
7291 #endif
7292 }
7293 END_TEST
7294 
7295 /* Test that non-name characters after a colon are rejected */
START_TEST(test_ns_bad_attr_leafname)7296 START_TEST(test_ns_bad_attr_leafname) {
7297   const char *text = "<foo:e xmlns:foo='http://example.org/' foo:?ar='baz' />";
7298 
7299   expect_failure(text, XML_ERROR_INVALID_TOKEN,
7300                  "Invalid character in leafname not faulted");
7301 }
7302 END_TEST
7303 
START_TEST(test_ns_bad_element_leafname)7304 START_TEST(test_ns_bad_element_leafname) {
7305   const char *text = "<foo:?oc xmlns:foo='http://example.org/' />";
7306 
7307   expect_failure(text, XML_ERROR_INVALID_TOKEN,
7308                  "Invalid character in element leafname not faulted");
7309 }
7310 END_TEST
7311 
7312 /* Test high-byte-set UTF-16 characters are valid in a leafname */
START_TEST(test_ns_utf16_leafname)7313 START_TEST(test_ns_utf16_leafname) {
7314   const char text[] =
7315       /* <n:e xmlns:n='URI' n:{KHO KHWAI}='a' />
7316        * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
7317        */
7318       "<\0n\0:\0e\0 \0x\0m\0l\0n\0s\0:\0n\0=\0'\0U\0R\0I\0'\0 \0"
7319       "n\0:\0\x04\x0e=\0'\0a\0'\0 \0/\0>\0";
7320   const XML_Char *expected = XCS("a");
7321   CharData storage;
7322 
7323   CharData_Init(&storage);
7324   XML_SetStartElementHandler(g_parser, accumulate_attribute);
7325   XML_SetUserData(g_parser, &storage);
7326   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
7327       == XML_STATUS_ERROR)
7328     xml_failure(g_parser);
7329   CharData_CheckXMLChars(&storage, expected);
7330 }
7331 END_TEST
7332 
START_TEST(test_ns_utf16_element_leafname)7333 START_TEST(test_ns_utf16_element_leafname) {
7334   const char text[] =
7335       /* <n:{KHO KHWAI} xmlns:n='URI'/>
7336        * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
7337        */
7338       "\0<\0n\0:\x0e\x04\0 \0x\0m\0l\0n\0s\0:\0n\0=\0'\0U\0R\0I\0'\0/\0>";
7339 #ifdef XML_UNICODE
7340   const XML_Char *expected = XCS("URI \x0e04");
7341 #else
7342   const XML_Char *expected = XCS("URI \xe0\xb8\x84");
7343 #endif
7344   CharData storage;
7345 
7346   CharData_Init(&storage);
7347   XML_SetStartElementHandler(g_parser, start_element_event_handler);
7348   XML_SetUserData(g_parser, &storage);
7349   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
7350       == XML_STATUS_ERROR)
7351     xml_failure(g_parser);
7352   CharData_CheckXMLChars(&storage, expected);
7353 }
7354 END_TEST
7355 
START_TEST(test_ns_utf16_doctype)7356 START_TEST(test_ns_utf16_doctype) {
7357   const char text[] =
7358       /* <!DOCTYPE foo:{KHO KHWAI} [ <!ENTITY bar 'baz'> ]>\n
7359        * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
7360        */
7361       "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0f\0o\0o\0:\x0e\x04\0 "
7362       "\0[\0 \0<\0!\0E\0N\0T\0I\0T\0Y\0 \0b\0a\0r\0 \0'\0b\0a\0z\0'\0>\0 "
7363       "\0]\0>\0\n"
7364       /* <foo:{KHO KHWAI} xmlns:foo='URI'>&bar;</foo:{KHO KHWAI}> */
7365       "\0<\0f\0o\0o\0:\x0e\x04\0 "
7366       "\0x\0m\0l\0n\0s\0:\0f\0o\0o\0=\0'\0U\0R\0I\0'\0>"
7367       "\0&\0b\0a\0r\0;"
7368       "\0<\0/\0f\0o\0o\0:\x0e\x04\0>";
7369 #ifdef XML_UNICODE
7370   const XML_Char *expected = XCS("URI \x0e04");
7371 #else
7372   const XML_Char *expected = XCS("URI \xe0\xb8\x84");
7373 #endif
7374   CharData storage;
7375 
7376   CharData_Init(&storage);
7377   XML_SetUserData(g_parser, &storage);
7378   XML_SetStartElementHandler(g_parser, start_element_event_handler);
7379   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
7380   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
7381       == XML_STATUS_ERROR)
7382     xml_failure(g_parser);
7383   CharData_CheckXMLChars(&storage, expected);
7384 }
7385 END_TEST
7386 
START_TEST(test_ns_invalid_doctype)7387 START_TEST(test_ns_invalid_doctype) {
7388   const char *text = "<!DOCTYPE foo:!bad [ <!ENTITY bar 'baz' ]>\n"
7389                      "<foo:!bad>&bar;</foo:!bad>";
7390 
7391   expect_failure(text, XML_ERROR_INVALID_TOKEN,
7392                  "Invalid character in document local name not faulted");
7393 }
7394 END_TEST
7395 
START_TEST(test_ns_double_colon_doctype)7396 START_TEST(test_ns_double_colon_doctype) {
7397   const char *text = "<!DOCTYPE foo:a:doc [ <!ENTITY bar 'baz' ]>\n"
7398                      "<foo:a:doc>&bar;</foo:a:doc>";
7399 
7400   expect_failure(text, XML_ERROR_SYNTAX,
7401                  "Double colon in document name not faulted");
7402 }
7403 END_TEST
7404 
START_TEST(test_ns_separator_in_uri)7405 START_TEST(test_ns_separator_in_uri) {
7406   struct test_case {
7407     enum XML_Status expectedStatus;
7408     const char *doc;
7409     XML_Char namesep;
7410   };
7411   struct test_case cases[] = {
7412       {XML_STATUS_OK, "<doc xmlns='one_two' />", XCS('\n')},
7413       {XML_STATUS_ERROR, "<doc xmlns='one&#x0A;two' />", XCS('\n')},
7414       {XML_STATUS_OK, "<doc xmlns='one:two' />", XCS(':')},
7415   };
7416 
7417   size_t i = 0;
7418   size_t failCount = 0;
7419   for (; i < sizeof(cases) / sizeof(cases[0]); i++) {
7420     XML_Parser parser = XML_ParserCreateNS(NULL, cases[i].namesep);
7421     XML_SetElementHandler(parser, dummy_start_element, dummy_end_element);
7422     if (XML_Parse(parser, cases[i].doc, (int)strlen(cases[i].doc),
7423                   /*isFinal*/ XML_TRUE)
7424         != cases[i].expectedStatus) {
7425       failCount++;
7426     }
7427     XML_ParserFree(parser);
7428   }
7429 
7430   if (failCount) {
7431     fail("Namespace separator handling is broken");
7432   }
7433 }
7434 END_TEST
7435 
7436 /* Control variable; the number of times duff_allocator() will successfully
7437  * allocate */
7438 #define ALLOC_ALWAYS_SUCCEED (-1)
7439 #define REALLOC_ALWAYS_SUCCEED (-1)
7440 
7441 static intptr_t allocation_count = ALLOC_ALWAYS_SUCCEED;
7442 static intptr_t reallocation_count = REALLOC_ALWAYS_SUCCEED;
7443 
7444 /* Crocked allocator for allocation failure tests */
7445 static void *
duff_allocator(size_t size)7446 duff_allocator(size_t size) {
7447   if (allocation_count == 0)
7448     return NULL;
7449   if (allocation_count != ALLOC_ALWAYS_SUCCEED)
7450     allocation_count--;
7451   return malloc(size);
7452 }
7453 
7454 /* Crocked reallocator for allocation failure tests */
7455 static void *
duff_reallocator(void * ptr,size_t size)7456 duff_reallocator(void *ptr, size_t size) {
7457   if (reallocation_count == 0)
7458     return NULL;
7459   if (reallocation_count != REALLOC_ALWAYS_SUCCEED)
7460     reallocation_count--;
7461   return realloc(ptr, size);
7462 }
7463 
7464 /* Test that a failure to allocate the parser structure fails gracefully */
START_TEST(test_misc_alloc_create_parser)7465 START_TEST(test_misc_alloc_create_parser) {
7466   XML_Memory_Handling_Suite memsuite = {duff_allocator, realloc, free};
7467   unsigned int i;
7468   const unsigned int max_alloc_count = 10;
7469 
7470   /* Something this simple shouldn't need more than 10 allocations */
7471   for (i = 0; i < max_alloc_count; i++) {
7472     allocation_count = i;
7473     g_parser = XML_ParserCreate_MM(NULL, &memsuite, NULL);
7474     if (g_parser != NULL)
7475       break;
7476   }
7477   if (i == 0)
7478     fail("Parser unexpectedly ignored failing allocator");
7479   else if (i == max_alloc_count)
7480     fail("Parser not created with max allocation count");
7481 }
7482 END_TEST
7483 
7484 /* Test memory allocation failures for a parser with an encoding */
START_TEST(test_misc_alloc_create_parser_with_encoding)7485 START_TEST(test_misc_alloc_create_parser_with_encoding) {
7486   XML_Memory_Handling_Suite memsuite = {duff_allocator, realloc, free};
7487   unsigned int i;
7488   const unsigned int max_alloc_count = 10;
7489 
7490   /* Try several levels of allocation */
7491   for (i = 0; i < max_alloc_count; i++) {
7492     allocation_count = i;
7493     g_parser = XML_ParserCreate_MM(XCS("us-ascii"), &memsuite, NULL);
7494     if (g_parser != NULL)
7495       break;
7496   }
7497   if (i == 0)
7498     fail("Parser ignored failing allocator");
7499   else if (i == max_alloc_count)
7500     fail("Parser not created with max allocation count");
7501 }
7502 END_TEST
7503 
7504 /* Test that freeing a NULL parser doesn't cause an explosion.
7505  * (Not actually tested anywhere else)
7506  */
START_TEST(test_misc_null_parser)7507 START_TEST(test_misc_null_parser) {
7508   XML_ParserFree(NULL);
7509 }
7510 END_TEST
7511 
7512 /* Test that XML_ErrorString rejects out-of-range codes */
START_TEST(test_misc_error_string)7513 START_TEST(test_misc_error_string) {
7514   if (XML_ErrorString((enum XML_Error) - 1) != NULL)
7515     fail("Negative error code not rejected");
7516   if (XML_ErrorString((enum XML_Error)100) != NULL)
7517     fail("Large error code not rejected");
7518 }
7519 END_TEST
7520 
7521 /* Test the version information is consistent */
7522 
7523 /* Since we are working in XML_LChars (potentially 16-bits), we
7524  * can't use the standard C library functions for character
7525  * manipulation and have to roll our own.
7526  */
7527 static int
parse_version(const XML_LChar * version_text,XML_Expat_Version * version_struct)7528 parse_version(const XML_LChar *version_text,
7529               XML_Expat_Version *version_struct) {
7530   if (! version_text)
7531     return XML_FALSE;
7532 
7533   while (*version_text != 0x00) {
7534     if (*version_text >= ASCII_0 && *version_text <= ASCII_9)
7535       break;
7536     version_text++;
7537   }
7538   if (*version_text == 0x00)
7539     return XML_FALSE;
7540 
7541   /* version_struct->major = strtoul(version_text, 10, &version_text) */
7542   version_struct->major = 0;
7543   while (*version_text >= ASCII_0 && *version_text <= ASCII_9) {
7544     version_struct->major
7545         = 10 * version_struct->major + (*version_text++ - ASCII_0);
7546   }
7547   if (*version_text++ != ASCII_PERIOD)
7548     return XML_FALSE;
7549 
7550   /* Now for the minor version number */
7551   version_struct->minor = 0;
7552   while (*version_text >= ASCII_0 && *version_text <= ASCII_9) {
7553     version_struct->minor
7554         = 10 * version_struct->minor + (*version_text++ - ASCII_0);
7555   }
7556   if (*version_text++ != ASCII_PERIOD)
7557     return XML_FALSE;
7558 
7559   /* Finally the micro version number */
7560   version_struct->micro = 0;
7561   while (*version_text >= ASCII_0 && *version_text <= ASCII_9) {
7562     version_struct->micro
7563         = 10 * version_struct->micro + (*version_text++ - ASCII_0);
7564   }
7565   if (*version_text != 0x00)
7566     return XML_FALSE;
7567   return XML_TRUE;
7568 }
7569 
7570 static int
versions_equal(const XML_Expat_Version * first,const XML_Expat_Version * second)7571 versions_equal(const XML_Expat_Version *first,
7572                const XML_Expat_Version *second) {
7573   return (first->major == second->major && first->minor == second->minor
7574           && first->micro == second->micro);
7575 }
7576 
START_TEST(test_misc_version)7577 START_TEST(test_misc_version) {
7578   XML_Expat_Version read_version = XML_ExpatVersionInfo();
7579   /* Silence compiler warning with the following assignment */
7580   XML_Expat_Version parsed_version = {0, 0, 0};
7581   const XML_LChar *version_text = XML_ExpatVersion();
7582 
7583   if (version_text == NULL)
7584     fail("Could not obtain version text");
7585   assert(version_text != NULL);
7586   if (! parse_version(version_text, &parsed_version))
7587     fail("Unable to parse version text");
7588   if (! versions_equal(&read_version, &parsed_version))
7589     fail("Version mismatch");
7590 
7591 #if ! defined(XML_UNICODE) || defined(XML_UNICODE_WCHAR_T)
7592   if (xcstrcmp(version_text, XCS("expat_2.4.7"))) /* needs bump on releases */
7593     fail("XML_*_VERSION in expat.h out of sync?\n");
7594 #else
7595   /* If we have XML_UNICODE defined but not XML_UNICODE_WCHAR_T
7596    * then XML_LChar is defined as char, for some reason.
7597    */
7598   if (strcmp(version_text, "expat_2.2.5")) /* needs bump on releases */
7599     fail("XML_*_VERSION in expat.h out of sync?\n");
7600 #endif /* ! defined(XML_UNICODE) || defined(XML_UNICODE_WCHAR_T) */
7601 }
7602 END_TEST
7603 
7604 /* Test feature information */
START_TEST(test_misc_features)7605 START_TEST(test_misc_features) {
7606   const XML_Feature *features = XML_GetFeatureList();
7607 
7608   /* Prevent problems with double-freeing parsers */
7609   g_parser = NULL;
7610   if (features == NULL) {
7611     fail("Failed to get feature information");
7612   } else {
7613     /* Loop through the features checking what we can */
7614     while (features->feature != XML_FEATURE_END) {
7615       switch (features->feature) {
7616       case XML_FEATURE_SIZEOF_XML_CHAR:
7617         if (features->value != sizeof(XML_Char))
7618           fail("Incorrect size of XML_Char");
7619         break;
7620       case XML_FEATURE_SIZEOF_XML_LCHAR:
7621         if (features->value != sizeof(XML_LChar))
7622           fail("Incorrect size of XML_LChar");
7623         break;
7624       default:
7625         break;
7626       }
7627       features++;
7628     }
7629   }
7630 }
7631 END_TEST
7632 
7633 /* Regression test for GitHub Issue #17: memory leak parsing attribute
7634  * values with mixed bound and unbound namespaces.
7635  */
START_TEST(test_misc_attribute_leak)7636 START_TEST(test_misc_attribute_leak) {
7637   const char *text = "<D xmlns:L=\"D\" l:a='' L:a=''/>";
7638   XML_Memory_Handling_Suite memsuite
7639       = {tracking_malloc, tracking_realloc, tracking_free};
7640 
7641   g_parser = XML_ParserCreate_MM(XCS("UTF-8"), &memsuite, XCS("\n"));
7642   expect_failure(text, XML_ERROR_UNBOUND_PREFIX, "Unbound prefixes not found");
7643   XML_ParserFree(g_parser);
7644   /* Prevent the teardown trying to double free */
7645   g_parser = NULL;
7646 
7647   if (! tracking_report())
7648     fail("Memory leak found");
7649 }
7650 END_TEST
7651 
7652 /* Test parser created for UTF-16LE is successful */
START_TEST(test_misc_utf16le)7653 START_TEST(test_misc_utf16le) {
7654   const char text[] =
7655       /* <?xml version='1.0'?><q>Hi</q> */
7656       "<\0?\0x\0m\0l\0 \0"
7657       "v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0?\0>\0"
7658       "<\0q\0>\0H\0i\0<\0/\0q\0>\0";
7659   const XML_Char *expected = XCS("Hi");
7660   CharData storage;
7661 
7662   g_parser = XML_ParserCreate(XCS("UTF-16LE"));
7663   if (g_parser == NULL)
7664     fail("Parser not created");
7665 
7666   CharData_Init(&storage);
7667   XML_SetUserData(g_parser, &storage);
7668   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
7669   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
7670       == XML_STATUS_ERROR)
7671     xml_failure(g_parser);
7672   CharData_CheckXMLChars(&storage, expected);
7673 }
7674 END_TEST
7675 
7676 typedef struct {
7677   XML_Parser parser;
7678   int deep;
7679 } DataIssue240;
7680 
7681 static void
start_element_issue_240(void * userData,const XML_Char * name,const XML_Char ** atts)7682 start_element_issue_240(void *userData, const XML_Char *name,
7683                         const XML_Char **atts) {
7684   DataIssue240 *mydata = (DataIssue240 *)userData;
7685   UNUSED_P(name);
7686   UNUSED_P(atts);
7687   mydata->deep++;
7688 }
7689 
7690 static void
end_element_issue_240(void * userData,const XML_Char * name)7691 end_element_issue_240(void *userData, const XML_Char *name) {
7692   DataIssue240 *mydata = (DataIssue240 *)userData;
7693 
7694   UNUSED_P(name);
7695   mydata->deep--;
7696   if (mydata->deep == 0) {
7697     XML_StopParser(mydata->parser, 0);
7698   }
7699 }
7700 
START_TEST(test_misc_stop_during_end_handler_issue_240_1)7701 START_TEST(test_misc_stop_during_end_handler_issue_240_1) {
7702   XML_Parser parser;
7703   DataIssue240 *mydata;
7704   enum XML_Status result;
7705   const char *const doc1 = "<doc><e1/><e><foo/></e></doc>";
7706 
7707   parser = XML_ParserCreate(NULL);
7708   XML_SetElementHandler(parser, start_element_issue_240, end_element_issue_240);
7709   mydata = (DataIssue240 *)malloc(sizeof(DataIssue240));
7710   mydata->parser = parser;
7711   mydata->deep = 0;
7712   XML_SetUserData(parser, mydata);
7713 
7714   result = XML_Parse(parser, doc1, (int)strlen(doc1), 1);
7715   XML_ParserFree(parser);
7716   free(mydata);
7717   if (result != XML_STATUS_ERROR)
7718     fail("Stopping the parser did not work as expected");
7719 }
7720 END_TEST
7721 
START_TEST(test_misc_stop_during_end_handler_issue_240_2)7722 START_TEST(test_misc_stop_during_end_handler_issue_240_2) {
7723   XML_Parser parser;
7724   DataIssue240 *mydata;
7725   enum XML_Status result;
7726   const char *const doc2 = "<doc><elem/></doc>";
7727 
7728   parser = XML_ParserCreate(NULL);
7729   XML_SetElementHandler(parser, start_element_issue_240, end_element_issue_240);
7730   mydata = (DataIssue240 *)malloc(sizeof(DataIssue240));
7731   mydata->parser = parser;
7732   mydata->deep = 0;
7733   XML_SetUserData(parser, mydata);
7734 
7735   result = XML_Parse(parser, doc2, (int)strlen(doc2), 1);
7736   XML_ParserFree(parser);
7737   free(mydata);
7738   if (result != XML_STATUS_ERROR)
7739     fail("Stopping the parser did not work as expected");
7740 }
7741 END_TEST
7742 
START_TEST(test_misc_deny_internal_entity_closing_doctype_issue_317)7743 START_TEST(test_misc_deny_internal_entity_closing_doctype_issue_317) {
7744   const char *const inputOne = "<!DOCTYPE d [\n"
7745                                "<!ENTITY % e ']><d/>'>\n"
7746                                "\n"
7747                                "%e;";
7748   const char *const inputTwo = "<!DOCTYPE d [\n"
7749                                "<!ENTITY % e1 ']><d/>'><!ENTITY % e2 '&e1;'>\n"
7750                                "\n"
7751                                "%e2;";
7752   const char *const inputThree = "<!DOCTYPE d [\n"
7753                                  "<!ENTITY % e ']><d'>\n"
7754                                  "\n"
7755                                  "%e;";
7756   const char *const inputIssue317 = "<!DOCTYPE doc [\n"
7757                                     "<!ENTITY % foo ']>\n"
7758                                     "<doc>Hell<oc (#PCDATA)*>'>\n"
7759                                     "%foo;\n"
7760                                     "]>\n"
7761                                     "<doc>Hello, world</dVc>";
7762 
7763   const char *const inputs[] = {inputOne, inputTwo, inputThree, inputIssue317};
7764   size_t inputIndex = 0;
7765 
7766   for (; inputIndex < sizeof(inputs) / sizeof(inputs[0]); inputIndex++) {
7767     XML_Parser parser;
7768     enum XML_Status parseResult;
7769     int setParamEntityResult;
7770     XML_Size lineNumber;
7771     XML_Size columnNumber;
7772     const char *const input = inputs[inputIndex];
7773 
7774     parser = XML_ParserCreate(NULL);
7775     setParamEntityResult
7776         = XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
7777     if (setParamEntityResult != 1)
7778       fail("Failed to set XML_PARAM_ENTITY_PARSING_ALWAYS.");
7779 
7780     parseResult = XML_Parse(parser, input, (int)strlen(input), 0);
7781     if (parseResult != XML_STATUS_ERROR) {
7782       parseResult = XML_Parse(parser, "", 0, 1);
7783       if (parseResult != XML_STATUS_ERROR) {
7784         fail("Parsing was expected to fail but succeeded.");
7785       }
7786     }
7787 
7788     if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN)
7789       fail("Error code does not match XML_ERROR_INVALID_TOKEN");
7790 
7791     lineNumber = XML_GetCurrentLineNumber(parser);
7792     if (lineNumber != 4)
7793       fail("XML_GetCurrentLineNumber does not work as expected.");
7794 
7795     columnNumber = XML_GetCurrentColumnNumber(parser);
7796     if (columnNumber != 0)
7797       fail("XML_GetCurrentColumnNumber does not work as expected.");
7798 
7799     XML_ParserFree(parser);
7800   }
7801 }
7802 END_TEST
7803 
7804 static void
alloc_setup(void)7805 alloc_setup(void) {
7806   XML_Memory_Handling_Suite memsuite = {duff_allocator, duff_reallocator, free};
7807 
7808   /* Ensure the parser creation will go through */
7809   allocation_count = ALLOC_ALWAYS_SUCCEED;
7810   reallocation_count = REALLOC_ALWAYS_SUCCEED;
7811   g_parser = XML_ParserCreate_MM(NULL, &memsuite, NULL);
7812   if (g_parser == NULL)
7813     fail("Parser not created");
7814 }
7815 
7816 static void
alloc_teardown(void)7817 alloc_teardown(void) {
7818   basic_teardown();
7819 }
7820 
7821 /* Test the effects of allocation failures on xml declaration processing */
START_TEST(test_alloc_parse_xdecl)7822 START_TEST(test_alloc_parse_xdecl) {
7823   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
7824                      "<doc>Hello, world</doc>";
7825   int i;
7826   const int max_alloc_count = 15;
7827 
7828   for (i = 0; i < max_alloc_count; i++) {
7829     allocation_count = i;
7830     XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler);
7831     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7832         != XML_STATUS_ERROR)
7833       break;
7834     /* Resetting the parser is insufficient, because some memory
7835      * allocations are cached within the parser.  Instead we use
7836      * the teardown and setup routines to ensure that we have the
7837      * right sort of parser back in our hands.
7838      */
7839     alloc_teardown();
7840     alloc_setup();
7841   }
7842   if (i == 0)
7843     fail("Parse succeeded despite failing allocator");
7844   if (i == max_alloc_count)
7845     fail("Parse failed with max allocations");
7846 }
7847 END_TEST
7848 
7849 /* As above, but with an encoding big enough to cause storing the
7850  * version information to expand the string pool being used.
7851  */
7852 static int XMLCALL
long_encoding_handler(void * userData,const XML_Char * encoding,XML_Encoding * info)7853 long_encoding_handler(void *userData, const XML_Char *encoding,
7854                       XML_Encoding *info) {
7855   int i;
7856 
7857   UNUSED_P(userData);
7858   UNUSED_P(encoding);
7859   for (i = 0; i < 256; i++)
7860     info->map[i] = i;
7861   info->data = NULL;
7862   info->convert = NULL;
7863   info->release = NULL;
7864   return XML_STATUS_OK;
7865 }
7866 
START_TEST(test_alloc_parse_xdecl_2)7867 START_TEST(test_alloc_parse_xdecl_2) {
7868   const char *text
7869       = "<?xml version='1.0' encoding='"
7870         /* Each line is 64 characters */
7871         "ThisIsAStupidlyLongEncodingNameIntendedToTriggerPoolGrowth123456"
7872         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7873         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7874         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7875         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7876         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7877         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7878         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7879         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7880         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7881         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7882         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7883         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7884         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7885         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7886         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN"
7887         "'?>"
7888         "<doc>Hello, world</doc>";
7889   int i;
7890   const int max_alloc_count = 20;
7891 
7892   for (i = 0; i < max_alloc_count; i++) {
7893     allocation_count = i;
7894     XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler);
7895     XML_SetUnknownEncodingHandler(g_parser, long_encoding_handler, NULL);
7896     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7897         != XML_STATUS_ERROR)
7898       break;
7899     /* See comment in test_alloc_parse_xdecl() */
7900     alloc_teardown();
7901     alloc_setup();
7902   }
7903   if (i == 0)
7904     fail("Parse succeeded despite failing allocator");
7905   if (i == max_alloc_count)
7906     fail("Parse failed with max allocations");
7907 }
7908 END_TEST
7909 
7910 /* Test the effects of allocation failures on a straightforward parse */
START_TEST(test_alloc_parse_pi)7911 START_TEST(test_alloc_parse_pi) {
7912   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
7913                      "<?pi unknown?>\n"
7914                      "<doc>"
7915                      "Hello, world"
7916                      "</doc>";
7917   int i;
7918   const int max_alloc_count = 15;
7919 
7920   for (i = 0; i < max_alloc_count; i++) {
7921     allocation_count = i;
7922     XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
7923     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7924         != XML_STATUS_ERROR)
7925       break;
7926     /* See comment in test_alloc_parse_xdecl() */
7927     alloc_teardown();
7928     alloc_setup();
7929   }
7930   if (i == 0)
7931     fail("Parse succeeded despite failing allocator");
7932   if (i == max_alloc_count)
7933     fail("Parse failed with max allocations");
7934 }
7935 END_TEST
7936 
START_TEST(test_alloc_parse_pi_2)7937 START_TEST(test_alloc_parse_pi_2) {
7938   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
7939                      "<doc>"
7940                      "Hello, world"
7941                      "<?pi unknown?>\n"
7942                      "</doc>";
7943   int i;
7944   const int max_alloc_count = 15;
7945 
7946   for (i = 0; i < max_alloc_count; i++) {
7947     allocation_count = i;
7948     XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
7949     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7950         != XML_STATUS_ERROR)
7951       break;
7952     /* See comment in test_alloc_parse_xdecl() */
7953     alloc_teardown();
7954     alloc_setup();
7955   }
7956   if (i == 0)
7957     fail("Parse succeeded despite failing allocator");
7958   if (i == max_alloc_count)
7959     fail("Parse failed with max allocations");
7960 }
7961 END_TEST
7962 
START_TEST(test_alloc_parse_pi_3)7963 START_TEST(test_alloc_parse_pi_3) {
7964   const char *text
7965       = "<?"
7966         /* 64 characters per line */
7967         "This processing instruction should be long enough to ensure that"
7968         "it triggers the growth of an internal string pool when the      "
7969         "allocator fails at a cruicial moment FGHIJKLMNOPABCDEFGHIJKLMNOP"
7970         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7971         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7972         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7973         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7974         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7975         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7976         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7977         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7978         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7979         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7980         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7981         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7982         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7983         "Q?><doc/>";
7984   int i;
7985   const int max_alloc_count = 20;
7986 
7987   for (i = 0; i < max_alloc_count; i++) {
7988     allocation_count = i;
7989     XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
7990     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7991         != XML_STATUS_ERROR)
7992       break;
7993     /* See comment in test_alloc_parse_xdecl() */
7994     alloc_teardown();
7995     alloc_setup();
7996   }
7997   if (i == 0)
7998     fail("Parse succeeded despite failing allocator");
7999   if (i == max_alloc_count)
8000     fail("Parse failed with max allocations");
8001 }
8002 END_TEST
8003 
START_TEST(test_alloc_parse_comment)8004 START_TEST(test_alloc_parse_comment) {
8005   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
8006                      "<!-- Test parsing this comment -->"
8007                      "<doc>Hi</doc>";
8008   int i;
8009   const int max_alloc_count = 15;
8010 
8011   for (i = 0; i < max_alloc_count; i++) {
8012     allocation_count = i;
8013     XML_SetCommentHandler(g_parser, dummy_comment_handler);
8014     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8015         != XML_STATUS_ERROR)
8016       break;
8017     /* See comment in test_alloc_parse_xdecl() */
8018     alloc_teardown();
8019     alloc_setup();
8020   }
8021   if (i == 0)
8022     fail("Parse succeeded despite failing allocator");
8023   if (i == max_alloc_count)
8024     fail("Parse failed with max allocations");
8025 }
8026 END_TEST
8027 
START_TEST(test_alloc_parse_comment_2)8028 START_TEST(test_alloc_parse_comment_2) {
8029   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
8030                      "<doc>"
8031                      "Hello, world"
8032                      "<!-- Parse this comment too -->"
8033                      "</doc>";
8034   int i;
8035   const int max_alloc_count = 15;
8036 
8037   for (i = 0; i < max_alloc_count; i++) {
8038     allocation_count = i;
8039     XML_SetCommentHandler(g_parser, dummy_comment_handler);
8040     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8041         != XML_STATUS_ERROR)
8042       break;
8043     /* See comment in test_alloc_parse_xdecl() */
8044     alloc_teardown();
8045     alloc_setup();
8046   }
8047   if (i == 0)
8048     fail("Parse succeeded despite failing allocator");
8049   if (i == max_alloc_count)
8050     fail("Parse failed with max allocations");
8051 }
8052 END_TEST
8053 
8054 static int XMLCALL
external_entity_duff_loader(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)8055 external_entity_duff_loader(XML_Parser parser, const XML_Char *context,
8056                             const XML_Char *base, const XML_Char *systemId,
8057                             const XML_Char *publicId) {
8058   XML_Parser new_parser;
8059   unsigned int i;
8060   const unsigned int max_alloc_count = 10;
8061 
8062   UNUSED_P(base);
8063   UNUSED_P(systemId);
8064   UNUSED_P(publicId);
8065   /* Try a few different allocation levels */
8066   for (i = 0; i < max_alloc_count; i++) {
8067     allocation_count = i;
8068     new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8069     if (new_parser != NULL) {
8070       XML_ParserFree(new_parser);
8071       break;
8072     }
8073   }
8074   if (i == 0)
8075     fail("External parser creation ignored failing allocator");
8076   else if (i == max_alloc_count)
8077     fail("Extern parser not created with max allocation count");
8078 
8079   /* Make sure other random allocation doesn't now fail */
8080   allocation_count = ALLOC_ALWAYS_SUCCEED;
8081 
8082   /* Make sure the failure code path is executed too */
8083   return XML_STATUS_ERROR;
8084 }
8085 
8086 /* Test that external parser creation running out of memory is
8087  * correctly reported.  Based on the external entity test cases.
8088  */
START_TEST(test_alloc_create_external_parser)8089 START_TEST(test_alloc_create_external_parser) {
8090   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
8091                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
8092                      "<doc>&entity;</doc>";
8093   char foo_text[] = "<!ELEMENT doc (#PCDATA)*>";
8094 
8095   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8096   XML_SetUserData(g_parser, foo_text);
8097   XML_SetExternalEntityRefHandler(g_parser, external_entity_duff_loader);
8098   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8099       != XML_STATUS_ERROR) {
8100     fail("External parser allocator returned success incorrectly");
8101   }
8102 }
8103 END_TEST
8104 
8105 /* More external parser memory allocation testing */
START_TEST(test_alloc_run_external_parser)8106 START_TEST(test_alloc_run_external_parser) {
8107   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
8108                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
8109                      "<doc>&entity;</doc>";
8110   char foo_text[] = "<!ELEMENT doc (#PCDATA)*>";
8111   unsigned int i;
8112   const unsigned int max_alloc_count = 15;
8113 
8114   for (i = 0; i < max_alloc_count; i++) {
8115     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8116     XML_SetUserData(g_parser, foo_text);
8117     XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader);
8118     allocation_count = i;
8119     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8120         != XML_STATUS_ERROR)
8121       break;
8122     /* See comment in test_alloc_parse_xdecl() */
8123     alloc_teardown();
8124     alloc_setup();
8125   }
8126   if (i == 0)
8127     fail("Parsing ignored failing allocator");
8128   else if (i == max_alloc_count)
8129     fail("Parsing failed with allocation count 10");
8130 }
8131 END_TEST
8132 
8133 static int XMLCALL
external_entity_dbl_handler(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)8134 external_entity_dbl_handler(XML_Parser parser, const XML_Char *context,
8135                             const XML_Char *base, const XML_Char *systemId,
8136                             const XML_Char *publicId) {
8137   intptr_t callno = (intptr_t)XML_GetUserData(parser);
8138   const char *text;
8139   XML_Parser new_parser;
8140   int i;
8141   const int max_alloc_count = 20;
8142 
8143   UNUSED_P(base);
8144   UNUSED_P(systemId);
8145   UNUSED_P(publicId);
8146   if (callno == 0) {
8147     /* First time through, check how many calls to malloc occur */
8148     text = ("<!ELEMENT doc (e+)>\n"
8149             "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
8150             "<!ELEMENT e EMPTY>\n");
8151     allocation_count = 10000;
8152     new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8153     if (new_parser == NULL) {
8154       fail("Unable to allocate first external parser");
8155       return XML_STATUS_ERROR;
8156     }
8157     /* Stash the number of calls in the user data */
8158     XML_SetUserData(parser, (void *)(intptr_t)(10000 - allocation_count));
8159   } else {
8160     text = ("<?xml version='1.0' encoding='us-ascii'?>"
8161             "<e/>");
8162     /* Try at varying levels to exercise more code paths */
8163     for (i = 0; i < max_alloc_count; i++) {
8164       allocation_count = callno + i;
8165       new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8166       if (new_parser != NULL)
8167         break;
8168     }
8169     if (i == 0) {
8170       fail("Second external parser unexpectedly created");
8171       XML_ParserFree(new_parser);
8172       return XML_STATUS_ERROR;
8173     } else if (i == max_alloc_count) {
8174       fail("Second external parser not created");
8175       return XML_STATUS_ERROR;
8176     }
8177   }
8178 
8179   allocation_count = ALLOC_ALWAYS_SUCCEED;
8180   if (_XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE)
8181       == XML_STATUS_ERROR) {
8182     xml_failure(new_parser);
8183     return XML_STATUS_ERROR;
8184   }
8185   XML_ParserFree(new_parser);
8186   return XML_STATUS_OK;
8187 }
8188 
8189 /* Test that running out of memory in dtdCopy is correctly reported.
8190  * Based on test_default_ns_from_ext_subset_and_ext_ge()
8191  */
START_TEST(test_alloc_dtd_copy_default_atts)8192 START_TEST(test_alloc_dtd_copy_default_atts) {
8193   const char *text = "<?xml version='1.0'?>\n"
8194                      "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n"
8195                      "  <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n"
8196                      "]>\n"
8197                      "<doc xmlns='http://example.org/ns1'>\n"
8198                      "&en;\n"
8199                      "</doc>";
8200 
8201   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8202   XML_SetExternalEntityRefHandler(g_parser, external_entity_dbl_handler);
8203   XML_SetUserData(g_parser, NULL);
8204   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8205       == XML_STATUS_ERROR)
8206     xml_failure(g_parser);
8207 }
8208 END_TEST
8209 
8210 static int XMLCALL
external_entity_dbl_handler_2(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)8211 external_entity_dbl_handler_2(XML_Parser parser, const XML_Char *context,
8212                               const XML_Char *base, const XML_Char *systemId,
8213                               const XML_Char *publicId) {
8214   intptr_t callno = (intptr_t)XML_GetUserData(parser);
8215   const char *text;
8216   XML_Parser new_parser;
8217   enum XML_Status rv;
8218 
8219   UNUSED_P(base);
8220   UNUSED_P(systemId);
8221   UNUSED_P(publicId);
8222   if (callno == 0) {
8223     /* Try different allocation levels for whole exercise */
8224     text = ("<!ELEMENT doc (e+)>\n"
8225             "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
8226             "<!ELEMENT e EMPTY>\n");
8227     XML_SetUserData(parser, (void *)(intptr_t)1);
8228     new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8229     if (new_parser == NULL)
8230       return XML_STATUS_ERROR;
8231     rv = _XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE);
8232   } else {
8233     /* Just run through once */
8234     text = ("<?xml version='1.0' encoding='us-ascii'?>"
8235             "<e/>");
8236     new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8237     if (new_parser == NULL)
8238       return XML_STATUS_ERROR;
8239     rv = _XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE);
8240   }
8241   XML_ParserFree(new_parser);
8242   if (rv == XML_STATUS_ERROR)
8243     return XML_STATUS_ERROR;
8244   return XML_STATUS_OK;
8245 }
8246 
8247 /* Test more external entity allocation failure paths */
START_TEST(test_alloc_external_entity)8248 START_TEST(test_alloc_external_entity) {
8249   const char *text = "<?xml version='1.0'?>\n"
8250                      "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n"
8251                      "  <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n"
8252                      "]>\n"
8253                      "<doc xmlns='http://example.org/ns1'>\n"
8254                      "&en;\n"
8255                      "</doc>";
8256   int i;
8257   const int alloc_test_max_repeats = 50;
8258 
8259   for (i = 0; i < alloc_test_max_repeats; i++) {
8260     allocation_count = -1;
8261     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8262     XML_SetExternalEntityRefHandler(g_parser, external_entity_dbl_handler_2);
8263     XML_SetUserData(g_parser, NULL);
8264     allocation_count = i;
8265     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8266         == XML_STATUS_OK)
8267       break;
8268     /* See comment in test_alloc_parse_xdecl() */
8269     alloc_teardown();
8270     alloc_setup();
8271   }
8272   allocation_count = -1;
8273   if (i == 0)
8274     fail("External entity parsed despite duff allocator");
8275   if (i == alloc_test_max_repeats)
8276     fail("External entity not parsed at max allocation count");
8277 }
8278 END_TEST
8279 
8280 /* Test more allocation failure paths */
8281 static int XMLCALL
external_entity_alloc_set_encoding(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)8282 external_entity_alloc_set_encoding(XML_Parser parser, const XML_Char *context,
8283                                    const XML_Char *base,
8284                                    const XML_Char *systemId,
8285                                    const XML_Char *publicId) {
8286   /* As for external_entity_loader() */
8287   const char *text = "<?xml encoding='iso-8859-3'?>"
8288                      "\xC3\xA9";
8289   XML_Parser ext_parser;
8290   enum XML_Status status;
8291 
8292   UNUSED_P(base);
8293   UNUSED_P(systemId);
8294   UNUSED_P(publicId);
8295   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8296   if (ext_parser == NULL)
8297     return XML_STATUS_ERROR;
8298   if (! XML_SetEncoding(ext_parser, XCS("utf-8"))) {
8299     XML_ParserFree(ext_parser);
8300     return XML_STATUS_ERROR;
8301   }
8302   status
8303       = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
8304   XML_ParserFree(ext_parser);
8305   if (status == XML_STATUS_ERROR)
8306     return XML_STATUS_ERROR;
8307   return XML_STATUS_OK;
8308 }
8309 
START_TEST(test_alloc_ext_entity_set_encoding)8310 START_TEST(test_alloc_ext_entity_set_encoding) {
8311   const char *text = "<!DOCTYPE doc [\n"
8312                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
8313                      "]>\n"
8314                      "<doc>&en;</doc>";
8315   int i;
8316   const int max_allocation_count = 30;
8317 
8318   for (i = 0; i < max_allocation_count; i++) {
8319     XML_SetExternalEntityRefHandler(g_parser,
8320                                     external_entity_alloc_set_encoding);
8321     allocation_count = i;
8322     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8323         == XML_STATUS_OK)
8324       break;
8325     allocation_count = -1;
8326     /* See comment in test_alloc_parse_xdecl() */
8327     alloc_teardown();
8328     alloc_setup();
8329   }
8330   if (i == 0)
8331     fail("Encoding check succeeded despite failing allocator");
8332   if (i == max_allocation_count)
8333     fail("Encoding failed at max allocation count");
8334 }
8335 END_TEST
8336 
8337 static int XMLCALL
unknown_released_encoding_handler(void * data,const XML_Char * encoding,XML_Encoding * info)8338 unknown_released_encoding_handler(void *data, const XML_Char *encoding,
8339                                   XML_Encoding *info) {
8340   UNUSED_P(data);
8341   if (! xcstrcmp(encoding, XCS("unsupported-encoding"))) {
8342     int i;
8343 
8344     for (i = 0; i < 256; i++)
8345       info->map[i] = i;
8346     info->data = NULL;
8347     info->convert = NULL;
8348     info->release = dummy_release;
8349     return XML_STATUS_OK;
8350   }
8351   return XML_STATUS_ERROR;
8352 }
8353 
8354 /* Test the effects of allocation failure in internal entities.
8355  * Based on test_unknown_encoding_internal_entity
8356  */
START_TEST(test_alloc_internal_entity)8357 START_TEST(test_alloc_internal_entity) {
8358   const char *text = "<?xml version='1.0' encoding='unsupported-encoding'?>\n"
8359                      "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n"
8360                      "<test a='&foo;'/>";
8361   unsigned int i;
8362   const unsigned int max_alloc_count = 20;
8363 
8364   for (i = 0; i < max_alloc_count; i++) {
8365     allocation_count = i;
8366     XML_SetUnknownEncodingHandler(g_parser, unknown_released_encoding_handler,
8367                                   NULL);
8368     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8369         != XML_STATUS_ERROR)
8370       break;
8371     /* See comment in test_alloc_parse_xdecl() */
8372     alloc_teardown();
8373     alloc_setup();
8374   }
8375   if (i == 0)
8376     fail("Internal entity worked despite failing allocations");
8377   else if (i == max_alloc_count)
8378     fail("Internal entity failed at max allocation count");
8379 }
8380 END_TEST
8381 
8382 /* Test the robustness against allocation failure of element handling
8383  * Based on test_dtd_default_handling().
8384  */
START_TEST(test_alloc_dtd_default_handling)8385 START_TEST(test_alloc_dtd_default_handling) {
8386   const char *text = "<!DOCTYPE doc [\n"
8387                      "<!ENTITY e SYSTEM 'http://example.org/e'>\n"
8388                      "<!NOTATION n SYSTEM 'http://example.org/n'>\n"
8389                      "<!ENTITY e1 SYSTEM 'http://example.org/e' NDATA n>\n"
8390                      "<!ELEMENT doc (#PCDATA)>\n"
8391                      "<!ATTLIST doc a CDATA #IMPLIED>\n"
8392                      "<?pi in dtd?>\n"
8393                      "<!--comment in dtd-->\n"
8394                      "]>\n"
8395                      "<doc><![CDATA[text in doc]]></doc>";
8396   const XML_Char *expected = XCS("\n\n\n\n\n\n\n\n\n<doc>text in doc</doc>");
8397   CharData storage;
8398   int i;
8399   const int max_alloc_count = 25;
8400 
8401   for (i = 0; i < max_alloc_count; i++) {
8402     allocation_count = i;
8403     dummy_handler_flags = 0;
8404     XML_SetDefaultHandler(g_parser, accumulate_characters);
8405     XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_handler,
8406                               dummy_end_doctype_handler);
8407     XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
8408     XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
8409     XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
8410     XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
8411     XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
8412     XML_SetCommentHandler(g_parser, dummy_comment_handler);
8413     XML_SetCdataSectionHandler(g_parser, dummy_start_cdata_handler,
8414                                dummy_end_cdata_handler);
8415     XML_SetUnparsedEntityDeclHandler(g_parser,
8416                                      dummy_unparsed_entity_decl_handler);
8417     CharData_Init(&storage);
8418     XML_SetUserData(g_parser, &storage);
8419     XML_SetCharacterDataHandler(g_parser, accumulate_characters);
8420     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8421         != XML_STATUS_ERROR)
8422       break;
8423     /* See comment in test_alloc_parse_xdecl() */
8424     alloc_teardown();
8425     alloc_setup();
8426   }
8427   if (i == 0)
8428     fail("Default DTD parsed despite allocation failures");
8429   if (i == max_alloc_count)
8430     fail("Default DTD not parsed with maximum alloc count");
8431   CharData_CheckXMLChars(&storage, expected);
8432   if (dummy_handler_flags
8433       != (DUMMY_START_DOCTYPE_HANDLER_FLAG | DUMMY_END_DOCTYPE_HANDLER_FLAG
8434           | DUMMY_ENTITY_DECL_HANDLER_FLAG | DUMMY_NOTATION_DECL_HANDLER_FLAG
8435           | DUMMY_ELEMENT_DECL_HANDLER_FLAG | DUMMY_ATTLIST_DECL_HANDLER_FLAG
8436           | DUMMY_COMMENT_HANDLER_FLAG | DUMMY_PI_HANDLER_FLAG
8437           | DUMMY_START_CDATA_HANDLER_FLAG | DUMMY_END_CDATA_HANDLER_FLAG
8438           | DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG))
8439     fail("Not all handlers were called");
8440 }
8441 END_TEST
8442 
8443 /* Test robustness of XML_SetEncoding() with a failing allocator */
START_TEST(test_alloc_explicit_encoding)8444 START_TEST(test_alloc_explicit_encoding) {
8445   int i;
8446   const int max_alloc_count = 5;
8447 
8448   for (i = 0; i < max_alloc_count; i++) {
8449     allocation_count = i;
8450     if (XML_SetEncoding(g_parser, XCS("us-ascii")) == XML_STATUS_OK)
8451       break;
8452   }
8453   if (i == 0)
8454     fail("Encoding set despite failing allocator");
8455   else if (i == max_alloc_count)
8456     fail("Encoding not set at max allocation count");
8457 }
8458 END_TEST
8459 
8460 /* Test robustness of XML_SetBase against a failing allocator */
START_TEST(test_alloc_set_base)8461 START_TEST(test_alloc_set_base) {
8462   const XML_Char *new_base = XCS("/local/file/name.xml");
8463   int i;
8464   const int max_alloc_count = 5;
8465 
8466   for (i = 0; i < max_alloc_count; i++) {
8467     allocation_count = i;
8468     if (XML_SetBase(g_parser, new_base) == XML_STATUS_OK)
8469       break;
8470   }
8471   if (i == 0)
8472     fail("Base set despite failing allocator");
8473   else if (i == max_alloc_count)
8474     fail("Base not set with max allocation count");
8475 }
8476 END_TEST
8477 
8478 /* Test buffer extension in the face of a duff reallocator */
START_TEST(test_alloc_realloc_buffer)8479 START_TEST(test_alloc_realloc_buffer) {
8480   const char *text = get_buffer_test_text;
8481   void *buffer;
8482   int i;
8483   const int max_realloc_count = 10;
8484 
8485   /* Get a smallish buffer */
8486   for (i = 0; i < max_realloc_count; i++) {
8487     reallocation_count = i;
8488     buffer = XML_GetBuffer(g_parser, 1536);
8489     if (buffer == NULL)
8490       fail("1.5K buffer reallocation failed");
8491     assert(buffer != NULL);
8492     memcpy(buffer, text, strlen(text));
8493     if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE)
8494         == XML_STATUS_OK)
8495       break;
8496     /* See comment in test_alloc_parse_xdecl() */
8497     alloc_teardown();
8498     alloc_setup();
8499   }
8500   reallocation_count = -1;
8501   if (i == 0)
8502     fail("Parse succeeded with no reallocation");
8503   else if (i == max_realloc_count)
8504     fail("Parse failed with max reallocation count");
8505 }
8506 END_TEST
8507 
8508 /* Same test for external entity parsers */
8509 static int XMLCALL
external_entity_reallocator(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)8510 external_entity_reallocator(XML_Parser parser, const XML_Char *context,
8511                             const XML_Char *base, const XML_Char *systemId,
8512                             const XML_Char *publicId) {
8513   const char *text = get_buffer_test_text;
8514   XML_Parser ext_parser;
8515   void *buffer;
8516   enum XML_Status status;
8517 
8518   UNUSED_P(base);
8519   UNUSED_P(systemId);
8520   UNUSED_P(publicId);
8521   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8522   if (ext_parser == NULL)
8523     fail("Could not create external entity parser");
8524 
8525   reallocation_count = (intptr_t)XML_GetUserData(parser);
8526   buffer = XML_GetBuffer(ext_parser, 1536);
8527   if (buffer == NULL)
8528     fail("Buffer allocation failed");
8529   assert(buffer != NULL);
8530   memcpy(buffer, text, strlen(text));
8531   status = XML_ParseBuffer(ext_parser, (int)strlen(text), XML_FALSE);
8532   reallocation_count = -1;
8533   XML_ParserFree(ext_parser);
8534   return (status == XML_STATUS_OK) ? XML_STATUS_OK : XML_STATUS_ERROR;
8535 }
8536 
START_TEST(test_alloc_ext_entity_realloc_buffer)8537 START_TEST(test_alloc_ext_entity_realloc_buffer) {
8538   const char *text = "<!DOCTYPE doc [\n"
8539                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
8540                      "]>\n"
8541                      "<doc>&en;</doc>";
8542   int i;
8543   const int max_realloc_count = 10;
8544 
8545   for (i = 0; i < max_realloc_count; i++) {
8546     XML_SetExternalEntityRefHandler(g_parser, external_entity_reallocator);
8547     XML_SetUserData(g_parser, (void *)(intptr_t)i);
8548     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8549         == XML_STATUS_OK)
8550       break;
8551     /* See comment in test_alloc_parse_xdecl() */
8552     alloc_teardown();
8553     alloc_setup();
8554   }
8555   if (i == 0)
8556     fail("Succeeded with no reallocations");
8557   if (i == max_realloc_count)
8558     fail("Failed with max reallocations");
8559 }
8560 END_TEST
8561 
8562 /* Test elements with many attributes are handled correctly */
START_TEST(test_alloc_realloc_many_attributes)8563 START_TEST(test_alloc_realloc_many_attributes) {
8564   const char *text = "<!DOCTYPE doc [\n"
8565                      "<!ATTLIST doc za CDATA 'default'>\n"
8566                      "<!ATTLIST doc zb CDATA 'def2'>\n"
8567                      "<!ATTLIST doc zc CDATA 'def3'>\n"
8568                      "]>\n"
8569                      "<doc a='1'"
8570                      "     b='2'"
8571                      "     c='3'"
8572                      "     d='4'"
8573                      "     e='5'"
8574                      "     f='6'"
8575                      "     g='7'"
8576                      "     h='8'"
8577                      "     i='9'"
8578                      "     j='10'"
8579                      "     k='11'"
8580                      "     l='12'"
8581                      "     m='13'"
8582                      "     n='14'"
8583                      "     p='15'"
8584                      "     q='16'"
8585                      "     r='17'"
8586                      "     s='18'>"
8587                      "</doc>";
8588   int i;
8589   const int max_realloc_count = 10;
8590 
8591   for (i = 0; i < max_realloc_count; i++) {
8592     reallocation_count = i;
8593     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8594         != XML_STATUS_ERROR)
8595       break;
8596     /* See comment in test_alloc_parse_xdecl() */
8597     alloc_teardown();
8598     alloc_setup();
8599   }
8600   if (i == 0)
8601     fail("Parse succeeded despite no reallocations");
8602   if (i == max_realloc_count)
8603     fail("Parse failed at max reallocations");
8604 }
8605 END_TEST
8606 
8607 /* Test handling of a public entity with failing allocator */
START_TEST(test_alloc_public_entity_value)8608 START_TEST(test_alloc_public_entity_value) {
8609   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
8610                      "<doc></doc>\n";
8611   char dtd_text[]
8612       = "<!ELEMENT doc EMPTY>\n"
8613         "<!ENTITY % e1 PUBLIC 'foo' 'bar.ent'>\n"
8614         "<!ENTITY % "
8615         /* Each line is 64 characters */
8616         "ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345"
8617         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8618         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8619         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8620         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8621         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8622         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8623         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8624         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8625         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8626         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8627         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8628         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8629         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8630         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8631         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8632         " '%e1;'>\n"
8633         "%e1;\n";
8634   int i;
8635   const int max_alloc_count = 50;
8636 
8637   for (i = 0; i < max_alloc_count; i++) {
8638     allocation_count = i;
8639     dummy_handler_flags = 0;
8640     XML_SetUserData(g_parser, dtd_text);
8641     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8642     XML_SetExternalEntityRefHandler(g_parser, external_entity_public);
8643     /* Provoke a particular code path */
8644     XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
8645     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8646         != XML_STATUS_ERROR)
8647       break;
8648     /* See comment in test_alloc_parse_xdecl() */
8649     alloc_teardown();
8650     alloc_setup();
8651   }
8652   if (i == 0)
8653     fail("Parsing worked despite failing allocation");
8654   if (i == max_alloc_count)
8655     fail("Parsing failed at max allocation count");
8656   if (dummy_handler_flags != DUMMY_ENTITY_DECL_HANDLER_FLAG)
8657     fail("Entity declaration handler not called");
8658 }
8659 END_TEST
8660 
START_TEST(test_alloc_realloc_subst_public_entity_value)8661 START_TEST(test_alloc_realloc_subst_public_entity_value) {
8662   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
8663                      "<doc></doc>\n";
8664   char dtd_text[]
8665       = "<!ELEMENT doc EMPTY>\n"
8666         "<!ENTITY % "
8667         /* Each line is 64 characters */
8668         "ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345"
8669         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8670         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8671         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8672         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8673         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8674         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8675         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8676         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8677         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8678         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8679         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8680         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8681         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8682         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8683         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8684         " PUBLIC 'foo' 'bar.ent'>\n"
8685         "%ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345"
8686         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8687         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8688         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8689         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8690         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8691         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8692         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8693         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8694         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8695         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8696         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8697         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8698         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8699         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8700         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP;";
8701   int i;
8702   const int max_realloc_count = 10;
8703 
8704   for (i = 0; i < max_realloc_count; i++) {
8705     reallocation_count = i;
8706     XML_SetUserData(g_parser, dtd_text);
8707     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8708     XML_SetExternalEntityRefHandler(g_parser, external_entity_public);
8709     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8710         != XML_STATUS_ERROR)
8711       break;
8712     /* See comment in test_alloc_parse_xdecl() */
8713     alloc_teardown();
8714     alloc_setup();
8715   }
8716   if (i == 0)
8717     fail("Parsing worked despite failing reallocation");
8718   if (i == max_realloc_count)
8719     fail("Parsing failed at max reallocation count");
8720 }
8721 END_TEST
8722 
START_TEST(test_alloc_parse_public_doctype)8723 START_TEST(test_alloc_parse_public_doctype) {
8724   const char *text
8725       = "<?xml version='1.0' encoding='utf-8'?>\n"
8726         "<!DOCTYPE doc PUBLIC '"
8727         /* 64 characters per line */
8728         "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/"
8729         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8730         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8731         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8732         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8733         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8734         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8735         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8736         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8737         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8738         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8739         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8740         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8741         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8742         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8743         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8744         "' 'test'>\n"
8745         "<doc></doc>";
8746   int i;
8747   const int max_alloc_count = 25;
8748 
8749   for (i = 0; i < max_alloc_count; i++) {
8750     allocation_count = i;
8751     dummy_handler_flags = 0;
8752     XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_decl_handler,
8753                               dummy_end_doctype_decl_handler);
8754     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8755         != XML_STATUS_ERROR)
8756       break;
8757     /* See comment in test_alloc_parse_xdecl() */
8758     alloc_teardown();
8759     alloc_setup();
8760   }
8761   if (i == 0)
8762     fail("Parse succeeded despite failing allocator");
8763   if (i == max_alloc_count)
8764     fail("Parse failed at maximum allocation count");
8765   if (dummy_handler_flags
8766       != (DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG
8767           | DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG))
8768     fail("Doctype handler functions not called");
8769 }
8770 END_TEST
8771 
START_TEST(test_alloc_parse_public_doctype_long_name)8772 START_TEST(test_alloc_parse_public_doctype_long_name) {
8773   const char *text
8774       = "<?xml version='1.0' encoding='utf-8'?>\n"
8775         "<!DOCTYPE doc PUBLIC 'http://example.com/foo' '"
8776         /* 64 characters per line */
8777         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8778         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8779         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8780         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8781         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8782         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8783         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8784         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8785         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8786         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8787         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8788         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8789         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8790         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8791         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8792         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8793         "'>\n"
8794         "<doc></doc>";
8795   int i;
8796   const int max_alloc_count = 25;
8797 
8798   for (i = 0; i < max_alloc_count; i++) {
8799     allocation_count = i;
8800     XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_decl_handler,
8801                               dummy_end_doctype_decl_handler);
8802     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8803         != XML_STATUS_ERROR)
8804       break;
8805     /* See comment in test_alloc_parse_xdecl() */
8806     alloc_teardown();
8807     alloc_setup();
8808   }
8809   if (i == 0)
8810     fail("Parse succeeded despite failing allocator");
8811   if (i == max_alloc_count)
8812     fail("Parse failed at maximum allocation count");
8813 }
8814 END_TEST
8815 
8816 static int XMLCALL
external_entity_alloc(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)8817 external_entity_alloc(XML_Parser parser, const XML_Char *context,
8818                       const XML_Char *base, const XML_Char *systemId,
8819                       const XML_Char *publicId) {
8820   const char *text = (const char *)XML_GetUserData(parser);
8821   XML_Parser ext_parser;
8822   int parse_res;
8823 
8824   UNUSED_P(base);
8825   UNUSED_P(systemId);
8826   UNUSED_P(publicId);
8827   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8828   if (ext_parser == NULL)
8829     return XML_STATUS_ERROR;
8830   parse_res
8831       = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
8832   XML_ParserFree(ext_parser);
8833   return parse_res;
8834 }
8835 
8836 /* Test foreign DTD handling */
START_TEST(test_alloc_set_foreign_dtd)8837 START_TEST(test_alloc_set_foreign_dtd) {
8838   const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n"
8839                       "<doc>&entity;</doc>";
8840   char text2[] = "<!ELEMENT doc (#PCDATA)*>";
8841   int i;
8842   const int max_alloc_count = 25;
8843 
8844   for (i = 0; i < max_alloc_count; i++) {
8845     allocation_count = i;
8846     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8847     XML_SetUserData(g_parser, &text2);
8848     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
8849     if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE)
8850       fail("Could not set foreign DTD");
8851     if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_TRUE)
8852         != XML_STATUS_ERROR)
8853       break;
8854     /* See comment in test_alloc_parse_xdecl() */
8855     alloc_teardown();
8856     alloc_setup();
8857   }
8858   if (i == 0)
8859     fail("Parse succeeded despite failing allocator");
8860   if (i == max_alloc_count)
8861     fail("Parse failed at maximum allocation count");
8862 }
8863 END_TEST
8864 
8865 /* Test based on ibm/valid/P32/ibm32v04.xml */
START_TEST(test_alloc_attribute_enum_value)8866 START_TEST(test_alloc_attribute_enum_value) {
8867   const char *text = "<?xml version='1.0' standalone='no'?>\n"
8868                      "<!DOCTYPE animal SYSTEM 'test.dtd'>\n"
8869                      "<animal>This is a \n    <a/>  \n\nyellow tiger</animal>";
8870   char dtd_text[] = "<!ELEMENT animal (#PCDATA|a)*>\n"
8871                     "<!ELEMENT a EMPTY>\n"
8872                     "<!ATTLIST animal xml:space (default|preserve) 'preserve'>";
8873   int i;
8874   const int max_alloc_count = 30;
8875 
8876   for (i = 0; i < max_alloc_count; i++) {
8877     allocation_count = i;
8878     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
8879     XML_SetUserData(g_parser, dtd_text);
8880     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8881     /* An attribute list handler provokes a different code path */
8882     XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
8883     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8884         != XML_STATUS_ERROR)
8885       break;
8886     /* See comment in test_alloc_parse_xdecl() */
8887     alloc_teardown();
8888     alloc_setup();
8889   }
8890   if (i == 0)
8891     fail("Parse succeeded despite failing allocator");
8892   if (i == max_alloc_count)
8893     fail("Parse failed at maximum allocation count");
8894 }
8895 END_TEST
8896 
8897 /* Test attribute enums sufficient to overflow the string pool */
START_TEST(test_alloc_realloc_attribute_enum_value)8898 START_TEST(test_alloc_realloc_attribute_enum_value) {
8899   const char *text = "<?xml version='1.0' standalone='no'?>\n"
8900                      "<!DOCTYPE animal SYSTEM 'test.dtd'>\n"
8901                      "<animal>This is a yellow tiger</animal>";
8902   /* We wish to define a collection of attribute enums that will
8903    * cause the string pool storing them to have to expand.  This
8904    * means more than 1024 bytes, including the parentheses and
8905    * separator bars.
8906    */
8907   char dtd_text[]
8908       = "<!ELEMENT animal (#PCDATA)*>\n"
8909         "<!ATTLIST animal thing "
8910         "(default"
8911         /* Each line is 64 characters */
8912         "|ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8913         "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8914         "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8915         "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8916         "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8917         "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8918         "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8919         "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8920         "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8921         "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8922         "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8923         "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8924         "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8925         "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8926         "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8927         "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO)"
8928         " 'default'>";
8929   int i;
8930   const int max_realloc_count = 10;
8931 
8932   for (i = 0; i < max_realloc_count; i++) {
8933     reallocation_count = i;
8934     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
8935     XML_SetUserData(g_parser, dtd_text);
8936     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8937     /* An attribute list handler provokes a different code path */
8938     XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
8939     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8940         != XML_STATUS_ERROR)
8941       break;
8942     /* See comment in test_alloc_parse_xdecl() */
8943     alloc_teardown();
8944     alloc_setup();
8945   }
8946   if (i == 0)
8947     fail("Parse succeeded despite failing reallocator");
8948   if (i == max_realloc_count)
8949     fail("Parse failed at maximum reallocation count");
8950 }
8951 END_TEST
8952 
8953 /* Test attribute enums in a #IMPLIED attribute forcing pool growth */
START_TEST(test_alloc_realloc_implied_attribute)8954 START_TEST(test_alloc_realloc_implied_attribute) {
8955   /* Forcing this particular code path is a balancing act.  The
8956    * addition of the closing parenthesis and terminal NUL must be
8957    * what pushes the string of enums over the 1024-byte limit,
8958    * otherwise a different code path will pick up the realloc.
8959    */
8960   const char *text
8961       = "<!DOCTYPE doc [\n"
8962         "<!ELEMENT doc EMPTY>\n"
8963         "<!ATTLIST doc a "
8964         /* Each line is 64 characters */
8965         "(ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8966         "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8967         "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8968         "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8969         "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8970         "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8971         "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8972         "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8973         "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8974         "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8975         "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8976         "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8977         "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8978         "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8979         "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8980         "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN)"
8981         " #IMPLIED>\n"
8982         "]><doc/>";
8983   int i;
8984   const int max_realloc_count = 10;
8985 
8986   for (i = 0; i < max_realloc_count; i++) {
8987     reallocation_count = i;
8988     XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
8989     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8990         != XML_STATUS_ERROR)
8991       break;
8992     /* See comment in test_alloc_parse_xdecl() */
8993     alloc_teardown();
8994     alloc_setup();
8995   }
8996   if (i == 0)
8997     fail("Parse succeeded despite failing reallocator");
8998   if (i == max_realloc_count)
8999     fail("Parse failed at maximum reallocation count");
9000 }
9001 END_TEST
9002 
9003 /* Test attribute enums in a defaulted attribute forcing pool growth */
START_TEST(test_alloc_realloc_default_attribute)9004 START_TEST(test_alloc_realloc_default_attribute) {
9005   /* Forcing this particular code path is a balancing act.  The
9006    * addition of the closing parenthesis and terminal NUL must be
9007    * what pushes the string of enums over the 1024-byte limit,
9008    * otherwise a different code path will pick up the realloc.
9009    */
9010   const char *text
9011       = "<!DOCTYPE doc [\n"
9012         "<!ELEMENT doc EMPTY>\n"
9013         "<!ATTLIST doc a "
9014         /* Each line is 64 characters */
9015         "(ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9016         "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9017         "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9018         "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9019         "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9020         "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9021         "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9022         "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9023         "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9024         "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9025         "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9026         "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9027         "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9028         "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9029         "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9030         "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN)"
9031         " 'ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO'"
9032         ">\n]><doc/>";
9033   int i;
9034   const int max_realloc_count = 10;
9035 
9036   for (i = 0; i < max_realloc_count; i++) {
9037     reallocation_count = i;
9038     XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
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   if (i == 0)
9047     fail("Parse succeeded despite failing reallocator");
9048   if (i == max_realloc_count)
9049     fail("Parse failed at maximum reallocation count");
9050 }
9051 END_TEST
9052 
9053 /* Test long notation name with dodgy allocator */
START_TEST(test_alloc_notation)9054 START_TEST(test_alloc_notation) {
9055   const char *text
9056       = "<!DOCTYPE doc [\n"
9057         "<!NOTATION "
9058         /* Each line is 64 characters */
9059         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9060         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9061         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9062         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9063         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9064         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9065         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9066         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9067         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9068         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9069         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9070         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9071         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9072         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9073         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9074         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9075         " SYSTEM 'http://example.org/n'>\n"
9076         "<!ENTITY e SYSTEM 'http://example.org/e' NDATA "
9077         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9078         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9079         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9080         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9081         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9082         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9083         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9084         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9085         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9086         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9087         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9088         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9089         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9090         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9091         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9092         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9093         ">\n"
9094         "<!ELEMENT doc EMPTY>\n"
9095         "]>\n<doc/>";
9096   int i;
9097   const int max_alloc_count = 20;
9098 
9099   for (i = 0; i < max_alloc_count; i++) {
9100     allocation_count = i;
9101     dummy_handler_flags = 0;
9102     XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
9103     XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
9104     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9105         != XML_STATUS_ERROR)
9106       break;
9107     /* See comment in test_alloc_parse_xdecl() */
9108     alloc_teardown();
9109     alloc_setup();
9110   }
9111   if (i == 0)
9112     fail("Parse succeeded despite allocation failures");
9113   if (i == max_alloc_count)
9114     fail("Parse failed at maximum allocation count");
9115   if (dummy_handler_flags
9116       != (DUMMY_ENTITY_DECL_HANDLER_FLAG | DUMMY_NOTATION_DECL_HANDLER_FLAG))
9117     fail("Entity declaration handler not called");
9118 }
9119 END_TEST
9120 
9121 /* Test public notation with dodgy allocator */
START_TEST(test_alloc_public_notation)9122 START_TEST(test_alloc_public_notation) {
9123   const char *text
9124       = "<!DOCTYPE doc [\n"
9125         "<!NOTATION note PUBLIC '"
9126         /* 64 characters per line */
9127         "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/"
9128         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9129         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9130         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9131         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9132         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9133         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9134         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9135         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9136         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9137         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9138         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9139         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9140         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9141         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9142         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9143         "' 'foo'>\n"
9144         "<!ENTITY e SYSTEM 'http://example.com/e' NDATA note>\n"
9145         "<!ELEMENT doc EMPTY>\n"
9146         "]>\n<doc/>";
9147   int i;
9148   const int max_alloc_count = 20;
9149 
9150   for (i = 0; i < max_alloc_count; i++) {
9151     allocation_count = i;
9152     dummy_handler_flags = 0;
9153     XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
9154     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9155         != XML_STATUS_ERROR)
9156       break;
9157     /* See comment in test_alloc_parse_xdecl() */
9158     alloc_teardown();
9159     alloc_setup();
9160   }
9161   if (i == 0)
9162     fail("Parse succeeded despite allocation failures");
9163   if (i == max_alloc_count)
9164     fail("Parse failed at maximum allocation count");
9165   if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG)
9166     fail("Notation handler not called");
9167 }
9168 END_TEST
9169 
9170 /* Test public notation with dodgy allocator */
START_TEST(test_alloc_system_notation)9171 START_TEST(test_alloc_system_notation) {
9172   const char *text
9173       = "<!DOCTYPE doc [\n"
9174         "<!NOTATION note SYSTEM '"
9175         /* 64 characters per line */
9176         "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/"
9177         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9178         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9179         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9180         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9181         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9182         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9183         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9184         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9185         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9186         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9187         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9188         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9189         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9190         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9191         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9192         "'>\n"
9193         "<!ENTITY e SYSTEM 'http://example.com/e' NDATA note>\n"
9194         "<!ELEMENT doc EMPTY>\n"
9195         "]>\n<doc/>";
9196   int i;
9197   const int max_alloc_count = 20;
9198 
9199   for (i = 0; i < max_alloc_count; i++) {
9200     allocation_count = i;
9201     dummy_handler_flags = 0;
9202     XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
9203     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9204         != XML_STATUS_ERROR)
9205       break;
9206     /* See comment in test_alloc_parse_xdecl() */
9207     alloc_teardown();
9208     alloc_setup();
9209   }
9210   if (i == 0)
9211     fail("Parse succeeded despite allocation failures");
9212   if (i == max_alloc_count)
9213     fail("Parse failed at maximum allocation count");
9214   if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG)
9215     fail("Notation handler not called");
9216 }
9217 END_TEST
9218 
START_TEST(test_alloc_nested_groups)9219 START_TEST(test_alloc_nested_groups) {
9220   const char *text
9221       = "<!DOCTYPE doc [\n"
9222         "<!ELEMENT doc "
9223         /* Sixteen elements per line */
9224         "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,"
9225         "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?"
9226         "))))))))))))))))))))))))))))))))>\n"
9227         "<!ELEMENT e EMPTY>"
9228         "]>\n"
9229         "<doc><e/></doc>";
9230   CharData storage;
9231   int i;
9232   const int max_alloc_count = 20;
9233 
9234   for (i = 0; i < max_alloc_count; i++) {
9235     allocation_count = i;
9236     CharData_Init(&storage);
9237     XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
9238     XML_SetStartElementHandler(g_parser, record_element_start_handler);
9239     XML_SetUserData(g_parser, &storage);
9240     dummy_handler_flags = 0;
9241     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9242         != XML_STATUS_ERROR)
9243       break;
9244     /* See comment in test_alloc_parse_xdecl() */
9245     alloc_teardown();
9246     alloc_setup();
9247   }
9248 
9249   if (i == 0)
9250     fail("Parse succeeded despite failing reallocator");
9251   if (i == max_alloc_count)
9252     fail("Parse failed at maximum reallocation count");
9253   CharData_CheckXMLChars(&storage, XCS("doce"));
9254   if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9255     fail("Element handler not fired");
9256 }
9257 END_TEST
9258 
START_TEST(test_alloc_realloc_nested_groups)9259 START_TEST(test_alloc_realloc_nested_groups) {
9260   const char *text
9261       = "<!DOCTYPE doc [\n"
9262         "<!ELEMENT doc "
9263         /* Sixteen elements per line */
9264         "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,"
9265         "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?"
9266         "))))))))))))))))))))))))))))))))>\n"
9267         "<!ELEMENT e EMPTY>"
9268         "]>\n"
9269         "<doc><e/></doc>";
9270   CharData storage;
9271   int i;
9272   const int max_realloc_count = 10;
9273 
9274   for (i = 0; i < max_realloc_count; i++) {
9275     reallocation_count = i;
9276     CharData_Init(&storage);
9277     XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
9278     XML_SetStartElementHandler(g_parser, record_element_start_handler);
9279     XML_SetUserData(g_parser, &storage);
9280     dummy_handler_flags = 0;
9281     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9282         != XML_STATUS_ERROR)
9283       break;
9284     /* See comment in test_alloc_parse_xdecl() */
9285     alloc_teardown();
9286     alloc_setup();
9287   }
9288 
9289   if (i == 0)
9290     fail("Parse succeeded despite failing reallocator");
9291   if (i == max_realloc_count)
9292     fail("Parse failed at maximum reallocation count");
9293   CharData_CheckXMLChars(&storage, XCS("doce"));
9294   if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9295     fail("Element handler not fired");
9296 }
9297 END_TEST
9298 
START_TEST(test_alloc_large_group)9299 START_TEST(test_alloc_large_group) {
9300   const char *text = "<!DOCTYPE doc [\n"
9301                      "<!ELEMENT doc ("
9302                      "a1|a2|a3|a4|a5|a6|a7|a8|"
9303                      "b1|b2|b3|b4|b5|b6|b7|b8|"
9304                      "c1|c2|c3|c4|c5|c6|c7|c8|"
9305                      "d1|d2|d3|d4|d5|d6|d7|d8|"
9306                      "e1"
9307                      ")+>\n"
9308                      "]>\n"
9309                      "<doc>\n"
9310                      "<a1/>\n"
9311                      "</doc>\n";
9312   int i;
9313   const int max_alloc_count = 50;
9314 
9315   for (i = 0; i < max_alloc_count; i++) {
9316     allocation_count = i;
9317     XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
9318     dummy_handler_flags = 0;
9319     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9320         != XML_STATUS_ERROR)
9321       break;
9322     /* See comment in test_alloc_parse_xdecl() */
9323     alloc_teardown();
9324     alloc_setup();
9325   }
9326   if (i == 0)
9327     fail("Parse succeeded despite failing allocator");
9328   if (i == max_alloc_count)
9329     fail("Parse failed at maximum allocation count");
9330   if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9331     fail("Element handler flag not raised");
9332 }
9333 END_TEST
9334 
START_TEST(test_alloc_realloc_group_choice)9335 START_TEST(test_alloc_realloc_group_choice) {
9336   const char *text = "<!DOCTYPE doc [\n"
9337                      "<!ELEMENT doc ("
9338                      "a1|a2|a3|a4|a5|a6|a7|a8|"
9339                      "b1|b2|b3|b4|b5|b6|b7|b8|"
9340                      "c1|c2|c3|c4|c5|c6|c7|c8|"
9341                      "d1|d2|d3|d4|d5|d6|d7|d8|"
9342                      "e1"
9343                      ")+>\n"
9344                      "]>\n"
9345                      "<doc>\n"
9346                      "<a1/>\n"
9347                      "<b2 attr='foo'>This is a foo</b2>\n"
9348                      "<c3></c3>\n"
9349                      "</doc>\n";
9350   int i;
9351   const int max_realloc_count = 10;
9352 
9353   for (i = 0; i < max_realloc_count; i++) {
9354     reallocation_count = i;
9355     XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
9356     dummy_handler_flags = 0;
9357     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9358         != XML_STATUS_ERROR)
9359       break;
9360     /* See comment in test_alloc_parse_xdecl() */
9361     alloc_teardown();
9362     alloc_setup();
9363   }
9364   if (i == 0)
9365     fail("Parse succeeded despite failing reallocator");
9366   if (i == max_realloc_count)
9367     fail("Parse failed at maximum reallocation count");
9368   if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9369     fail("Element handler flag not raised");
9370 }
9371 END_TEST
9372 
START_TEST(test_alloc_pi_in_epilog)9373 START_TEST(test_alloc_pi_in_epilog) {
9374   const char *text = "<doc></doc>\n"
9375                      "<?pi in epilog?>";
9376   int i;
9377   const int max_alloc_count = 15;
9378 
9379   for (i = 0; i < max_alloc_count; i++) {
9380     allocation_count = i;
9381     XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
9382     dummy_handler_flags = 0;
9383     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9384         != XML_STATUS_ERROR)
9385       break;
9386     /* See comment in test_alloc_parse_xdecl() */
9387     alloc_teardown();
9388     alloc_setup();
9389   }
9390   if (i == 0)
9391     fail("Parse completed despite failing allocator");
9392   if (i == max_alloc_count)
9393     fail("Parse failed at maximum allocation count");
9394   if (dummy_handler_flags != DUMMY_PI_HANDLER_FLAG)
9395     fail("Processing instruction handler not invoked");
9396 }
9397 END_TEST
9398 
START_TEST(test_alloc_comment_in_epilog)9399 START_TEST(test_alloc_comment_in_epilog) {
9400   const char *text = "<doc></doc>\n"
9401                      "<!-- comment in epilog -->";
9402   int i;
9403   const int max_alloc_count = 15;
9404 
9405   for (i = 0; i < max_alloc_count; i++) {
9406     allocation_count = i;
9407     XML_SetCommentHandler(g_parser, dummy_comment_handler);
9408     dummy_handler_flags = 0;
9409     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9410         != XML_STATUS_ERROR)
9411       break;
9412     /* See comment in test_alloc_parse_xdecl() */
9413     alloc_teardown();
9414     alloc_setup();
9415   }
9416   if (i == 0)
9417     fail("Parse completed despite failing allocator");
9418   if (i == max_alloc_count)
9419     fail("Parse failed at maximum allocation count");
9420   if (dummy_handler_flags != DUMMY_COMMENT_HANDLER_FLAG)
9421     fail("Processing instruction handler not invoked");
9422 }
9423 END_TEST
9424 
START_TEST(test_alloc_realloc_long_attribute_value)9425 START_TEST(test_alloc_realloc_long_attribute_value) {
9426   const char *text
9427       = "<!DOCTYPE doc [<!ENTITY foo '"
9428         /* Each line is 64 characters */
9429         "This entity will be substituted as an attribute value, and is   "
9430         "calculated to be exactly long enough that the terminating NUL   "
9431         "that the library adds internally will trigger the string pool to"
9432         "grow. GHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9433         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9434         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9435         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9436         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9437         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9438         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9439         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9440         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9441         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9442         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9443         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9444         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9445         "'>]>\n"
9446         "<doc a='&foo;'></doc>";
9447   int i;
9448   const int max_realloc_count = 10;
9449 
9450   for (i = 0; i < max_realloc_count; i++) {
9451     reallocation_count = i;
9452     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9453         != XML_STATUS_ERROR)
9454       break;
9455     /* See comment in test_alloc_parse_xdecl() */
9456     alloc_teardown();
9457     alloc_setup();
9458   }
9459   if (i == 0)
9460     fail("Parse succeeded despite failing reallocator");
9461   if (i == max_realloc_count)
9462     fail("Parse failed at maximum reallocation count");
9463 }
9464 END_TEST
9465 
START_TEST(test_alloc_attribute_whitespace)9466 START_TEST(test_alloc_attribute_whitespace) {
9467   const char *text = "<doc a=' '></doc>";
9468   int i;
9469   const int max_alloc_count = 15;
9470 
9471   for (i = 0; i < max_alloc_count; i++) {
9472     allocation_count = i;
9473     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9474         != XML_STATUS_ERROR)
9475       break;
9476     /* See comment in test_alloc_parse_xdecl() */
9477     alloc_teardown();
9478     alloc_setup();
9479   }
9480   if (i == 0)
9481     fail("Parse succeeded despite failing allocator");
9482   if (i == max_alloc_count)
9483     fail("Parse failed at maximum allocation count");
9484 }
9485 END_TEST
9486 
START_TEST(test_alloc_attribute_predefined_entity)9487 START_TEST(test_alloc_attribute_predefined_entity) {
9488   const char *text = "<doc a='&amp;'></doc>";
9489   int i;
9490   const int max_alloc_count = 15;
9491 
9492   for (i = 0; i < max_alloc_count; i++) {
9493     allocation_count = i;
9494     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9495         != XML_STATUS_ERROR)
9496       break;
9497     /* See comment in test_alloc_parse_xdecl() */
9498     alloc_teardown();
9499     alloc_setup();
9500   }
9501   if (i == 0)
9502     fail("Parse succeeded despite failing allocator");
9503   if (i == max_alloc_count)
9504     fail("Parse failed at maximum allocation count");
9505 }
9506 END_TEST
9507 
9508 /* Test that a character reference at the end of a suitably long
9509  * default value for an attribute can trigger pool growth, and recovers
9510  * if the allocator fails on it.
9511  */
START_TEST(test_alloc_long_attr_default_with_char_ref)9512 START_TEST(test_alloc_long_attr_default_with_char_ref) {
9513   const char *text
9514       = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '"
9515         /* 64 characters per line */
9516         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9517         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9518         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9519         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9520         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9521         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9522         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9523         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9524         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9525         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9526         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9527         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9528         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9529         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9530         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9531         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHI"
9532         "&#x31;'>]>\n"
9533         "<doc/>";
9534   int i;
9535   const int max_alloc_count = 20;
9536 
9537   for (i = 0; i < max_alloc_count; i++) {
9538     allocation_count = i;
9539     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9540         != XML_STATUS_ERROR)
9541       break;
9542     /* See comment in test_alloc_parse_xdecl() */
9543     alloc_teardown();
9544     alloc_setup();
9545   }
9546   if (i == 0)
9547     fail("Parse succeeded despite failing allocator");
9548   if (i == max_alloc_count)
9549     fail("Parse failed at maximum allocation count");
9550 }
9551 END_TEST
9552 
9553 /* Test that a long character reference substitution triggers a pool
9554  * expansion correctly for an attribute value.
9555  */
START_TEST(test_alloc_long_attr_value)9556 START_TEST(test_alloc_long_attr_value) {
9557   const char *text
9558       = "<!DOCTYPE test [<!ENTITY foo '\n"
9559         /* 64 characters per line */
9560         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9561         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9562         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9563         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9564         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9565         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9566         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9567         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9568         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9569         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9570         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9571         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9572         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9573         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9574         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9575         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9576         "'>]>\n"
9577         "<test a='&foo;'/>";
9578   int i;
9579   const int max_alloc_count = 25;
9580 
9581   for (i = 0; i < max_alloc_count; i++) {
9582     allocation_count = i;
9583     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9584         != XML_STATUS_ERROR)
9585       break;
9586     /* See comment in test_alloc_parse_xdecl() */
9587     alloc_teardown();
9588     alloc_setup();
9589   }
9590   if (i == 0)
9591     fail("Parse succeeded despite failing allocator");
9592   if (i == max_alloc_count)
9593     fail("Parse failed at maximum allocation count");
9594 }
9595 END_TEST
9596 
9597 /* Test that an error in a nested parameter entity substitution is
9598  * handled correctly.  It seems unlikely that the code path being
9599  * exercised can be reached purely by carefully crafted XML, but an
9600  * allocation error in the right place will definitely do it.
9601  */
START_TEST(test_alloc_nested_entities)9602 START_TEST(test_alloc_nested_entities) {
9603   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n"
9604                      "<doc />";
9605   ExtFaults test_data
9606       = {"<!ENTITY % pe1 '"
9607          /* 64 characters per line */
9608          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9609          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9610          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9611          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9612          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9613          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9614          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9615          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9616          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9617          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9618          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9619          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9620          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9621          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9622          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9623          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9624          "'>\n"
9625          "<!ENTITY % pe2 '%pe1;'>\n"
9626          "%pe2;",
9627          "Memory Fail not faulted", NULL, XML_ERROR_NO_MEMORY};
9628 
9629   /* Causes an allocation error in a nested storeEntityValue() */
9630   allocation_count = 12;
9631   XML_SetUserData(g_parser, &test_data);
9632   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9633   XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
9634   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
9635                  "Entity allocation failure not noted");
9636 }
9637 END_TEST
9638 
START_TEST(test_alloc_realloc_param_entity_newline)9639 START_TEST(test_alloc_realloc_param_entity_newline) {
9640   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
9641                      "<doc/>";
9642   char dtd_text[]
9643       = "<!ENTITY % pe '<!ATTLIST doc att CDATA \""
9644         /* 64 characters per line */
9645         "This default value is carefully crafted so that the carriage    "
9646         "return right at the end of the entity string causes an internal "
9647         "string pool to have to grow.  This allows us to test the alloc  "
9648         "failure path from that point. OPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9649         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9650         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9651         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9652         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9653         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9654         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9655         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9656         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9657         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9658         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9659         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9660         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDE"
9661         "\">\n'>"
9662         "%pe;\n";
9663   int i;
9664   const int max_realloc_count = 5;
9665 
9666   for (i = 0; i < max_realloc_count; i++) {
9667     reallocation_count = i;
9668     XML_SetUserData(g_parser, dtd_text);
9669     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9670     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9671     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9672         != XML_STATUS_ERROR)
9673       break;
9674     /* See comment in test_alloc_parse_xdecl() */
9675     alloc_teardown();
9676     alloc_setup();
9677   }
9678   if (i == 0)
9679     fail("Parse succeeded despite failing reallocator");
9680   if (i == max_realloc_count)
9681     fail("Parse failed at maximum reallocation count");
9682 }
9683 END_TEST
9684 
START_TEST(test_alloc_realloc_ce_extends_pe)9685 START_TEST(test_alloc_realloc_ce_extends_pe) {
9686   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
9687                      "<doc/>";
9688   char dtd_text[]
9689       = "<!ENTITY % pe '<!ATTLIST doc att CDATA \""
9690         /* 64 characters per line */
9691         "This default value is carefully crafted so that the character   "
9692         "entity at the end causes an internal string pool to have to     "
9693         "grow.  This allows us to test the allocation failure path from  "
9694         "that point onwards. EFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9695         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9696         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9697         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9698         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9699         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9700         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9701         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9702         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9703         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9704         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9705         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9706         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFG&#x51;"
9707         "\">\n'>"
9708         "%pe;\n";
9709   int i;
9710   const int max_realloc_count = 5;
9711 
9712   for (i = 0; i < max_realloc_count; i++) {
9713     reallocation_count = i;
9714     XML_SetUserData(g_parser, dtd_text);
9715     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9716     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9717     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9718         != XML_STATUS_ERROR)
9719       break;
9720     /* See comment in test_alloc_parse_xdecl() */
9721     alloc_teardown();
9722     alloc_setup();
9723   }
9724   if (i == 0)
9725     fail("Parse succeeded despite failing reallocator");
9726   if (i == max_realloc_count)
9727     fail("Parse failed at maximum reallocation count");
9728 }
9729 END_TEST
9730 
START_TEST(test_alloc_realloc_attributes)9731 START_TEST(test_alloc_realloc_attributes) {
9732   const char *text = "<!DOCTYPE doc [\n"
9733                      "  <!ATTLIST doc\n"
9734                      "    a1  (a|b|c)   'a'\n"
9735                      "    a2  (foo|bar) #IMPLIED\n"
9736                      "    a3  NMTOKEN   #IMPLIED\n"
9737                      "    a4  NMTOKENS  #IMPLIED\n"
9738                      "    a5  ID        #IMPLIED\n"
9739                      "    a6  IDREF     #IMPLIED\n"
9740                      "    a7  IDREFS    #IMPLIED\n"
9741                      "    a8  ENTITY    #IMPLIED\n"
9742                      "    a9  ENTITIES  #IMPLIED\n"
9743                      "    a10 CDATA     #IMPLIED\n"
9744                      "  >]>\n"
9745                      "<doc>wombat</doc>\n";
9746   int i;
9747   const int max_realloc_count = 5;
9748 
9749   for (i = 0; i < max_realloc_count; i++) {
9750     reallocation_count = i;
9751     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9752         != XML_STATUS_ERROR)
9753       break;
9754     /* See comment in test_alloc_parse_xdecl() */
9755     alloc_teardown();
9756     alloc_setup();
9757   }
9758 
9759   if (i == 0)
9760     fail("Parse succeeded despite failing reallocator");
9761   if (i == max_realloc_count)
9762     fail("Parse failed at maximum reallocation count");
9763 }
9764 END_TEST
9765 
START_TEST(test_alloc_long_doc_name)9766 START_TEST(test_alloc_long_doc_name) {
9767   const char *text =
9768       /* 64 characters per line */
9769       "<LongRootElementNameThatWillCauseTheNextAllocationToExpandTheStr"
9770       "ingPoolForTheDTDQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9771       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9772       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9773       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9774       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9775       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9776       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9777       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9778       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9779       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9780       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9781       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9782       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9783       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9784       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9785       " a='1'/>";
9786   int i;
9787   const int max_alloc_count = 20;
9788 
9789   for (i = 0; i < max_alloc_count; i++) {
9790     allocation_count = i;
9791     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9792         != XML_STATUS_ERROR)
9793       break;
9794     /* See comment in test_alloc_parse_xdecl() */
9795     alloc_teardown();
9796     alloc_setup();
9797   }
9798   if (i == 0)
9799     fail("Parsing worked despite failing reallocations");
9800   else if (i == max_alloc_count)
9801     fail("Parsing failed even at max reallocation count");
9802 }
9803 END_TEST
9804 
START_TEST(test_alloc_long_base)9805 START_TEST(test_alloc_long_base) {
9806   const char *text = "<!DOCTYPE doc [\n"
9807                      "  <!ENTITY e SYSTEM 'foo'>\n"
9808                      "]>\n"
9809                      "<doc>&e;</doc>";
9810   char entity_text[] = "Hello world";
9811   const XML_Char *base =
9812       /* 64 characters per line */
9813       /* clang-format off */
9814         XCS("LongBaseURI/that/will/overflow/an/internal/buffer/and/cause/it/t")
9815         XCS("o/have/to/grow/PQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9816         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9817         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9818         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9819         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9820         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9821         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9822         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9823         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9824         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9825         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9826         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9827         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9828         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9829         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/");
9830   /* clang-format on */
9831   int i;
9832   const int max_alloc_count = 25;
9833 
9834   for (i = 0; i < max_alloc_count; i++) {
9835     allocation_count = i;
9836     XML_SetUserData(g_parser, entity_text);
9837     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9838     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9839     if (XML_SetBase(g_parser, base) == XML_STATUS_ERROR) {
9840       XML_ParserReset(g_parser, NULL);
9841       continue;
9842     }
9843     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9844         != XML_STATUS_ERROR)
9845       break;
9846     /* See comment in test_alloc_parse_xdecl() */
9847     alloc_teardown();
9848     alloc_setup();
9849   }
9850   if (i == 0)
9851     fail("Parsing worked despite failing allocations");
9852   else if (i == max_alloc_count)
9853     fail("Parsing failed even at max allocation count");
9854 }
9855 END_TEST
9856 
START_TEST(test_alloc_long_public_id)9857 START_TEST(test_alloc_long_public_id) {
9858   const char *text
9859       = "<!DOCTYPE doc [\n"
9860         "  <!ENTITY e PUBLIC '"
9861         /* 64 characters per line */
9862         "LongPublicIDThatShouldResultInAnInternalStringPoolGrowingAtASpec"
9863         "ificMomentKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9864         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9865         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9866         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9867         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9868         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9869         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9870         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9871         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9872         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9873         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9874         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9875         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9876         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9877         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9878         "' 'bar'>\n"
9879         "]>\n"
9880         "<doc>&e;</doc>";
9881   char entity_text[] = "Hello world";
9882   int i;
9883   const int max_alloc_count = 40;
9884 
9885   for (i = 0; i < max_alloc_count; i++) {
9886     allocation_count = i;
9887     XML_SetUserData(g_parser, entity_text);
9888     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9889     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9890     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9891         != XML_STATUS_ERROR)
9892       break;
9893     /* See comment in test_alloc_parse_xdecl() */
9894     alloc_teardown();
9895     alloc_setup();
9896   }
9897   if (i == 0)
9898     fail("Parsing worked despite failing allocations");
9899   else if (i == max_alloc_count)
9900     fail("Parsing failed even at max allocation count");
9901 }
9902 END_TEST
9903 
START_TEST(test_alloc_long_entity_value)9904 START_TEST(test_alloc_long_entity_value) {
9905   const char *text
9906       = "<!DOCTYPE doc [\n"
9907         "  <!ENTITY e1 '"
9908         /* 64 characters per line */
9909         "Long entity value that should provoke a string pool to grow whil"
9910         "e setting up to parse the external entity below. xyz0123456789AB"
9911         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9912         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9913         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9914         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9915         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9916         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9917         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9918         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9919         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9920         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9921         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9922         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9923         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9924         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9925         "'>\n"
9926         "  <!ENTITY e2 SYSTEM 'bar'>\n"
9927         "]>\n"
9928         "<doc>&e2;</doc>";
9929   char entity_text[] = "Hello world";
9930   int i;
9931   const int max_alloc_count = 40;
9932 
9933   for (i = 0; i < max_alloc_count; i++) {
9934     allocation_count = i;
9935     XML_SetUserData(g_parser, entity_text);
9936     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9937     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9938     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9939         != XML_STATUS_ERROR)
9940       break;
9941     /* See comment in test_alloc_parse_xdecl() */
9942     alloc_teardown();
9943     alloc_setup();
9944   }
9945   if (i == 0)
9946     fail("Parsing worked despite failing allocations");
9947   else if (i == max_alloc_count)
9948     fail("Parsing failed even at max allocation count");
9949 }
9950 END_TEST
9951 
START_TEST(test_alloc_long_notation)9952 START_TEST(test_alloc_long_notation) {
9953   const char *text
9954       = "<!DOCTYPE doc [\n"
9955         "  <!NOTATION note SYSTEM '"
9956         /* 64 characters per line */
9957         "ALongNotationNameThatShouldProvokeStringPoolGrowthWhileCallingAn"
9958         "ExternalEntityParserUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9959         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9960         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9961         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9962         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9963         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9964         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9965         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9966         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9967         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9968         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9969         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9970         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9971         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9972         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9973         "'>\n"
9974         "  <!ENTITY e1 SYSTEM 'foo' NDATA "
9975         /* 64 characters per line */
9976         "ALongNotationNameThatShouldProvokeStringPoolGrowthWhileCallingAn"
9977         "ExternalEntityParserUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9978         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9979         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9980         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9981         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9982         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9983         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9984         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9985         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9986         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9987         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9988         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9989         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9990         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9991         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9992         ">\n"
9993         "  <!ENTITY e2 SYSTEM 'bar'>\n"
9994         "]>\n"
9995         "<doc>&e2;</doc>";
9996   ExtOption options[]
9997       = {{XCS("foo"), "Entity Foo"}, {XCS("bar"), "Entity Bar"}, {NULL, NULL}};
9998   int i;
9999   const int max_alloc_count = 40;
10000 
10001   for (i = 0; i < max_alloc_count; i++) {
10002     allocation_count = i;
10003     XML_SetUserData(g_parser, options);
10004     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
10005     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
10006     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10007         != XML_STATUS_ERROR)
10008       break;
10009 
10010     /* See comment in test_alloc_parse_xdecl() */
10011     alloc_teardown();
10012     alloc_setup();
10013   }
10014   if (i == 0)
10015     fail("Parsing worked despite failing allocations");
10016   else if (i == max_alloc_count)
10017     fail("Parsing failed even at max allocation count");
10018 }
10019 END_TEST
10020 
10021 static void
nsalloc_setup(void)10022 nsalloc_setup(void) {
10023   XML_Memory_Handling_Suite memsuite = {duff_allocator, duff_reallocator, free};
10024   XML_Char ns_sep[2] = {' ', '\0'};
10025 
10026   /* Ensure the parser creation will go through */
10027   allocation_count = ALLOC_ALWAYS_SUCCEED;
10028   reallocation_count = REALLOC_ALWAYS_SUCCEED;
10029   g_parser = XML_ParserCreate_MM(NULL, &memsuite, ns_sep);
10030   if (g_parser == NULL)
10031     fail("Parser not created");
10032 }
10033 
10034 static void
nsalloc_teardown(void)10035 nsalloc_teardown(void) {
10036   basic_teardown();
10037 }
10038 
10039 /* Test the effects of allocation failure in simple namespace parsing.
10040  * Based on test_ns_default_with_empty_uri()
10041  */
START_TEST(test_nsalloc_xmlns)10042 START_TEST(test_nsalloc_xmlns) {
10043   const char *text = "<doc xmlns='http://example.org/'>\n"
10044                      "  <e xmlns=''/>\n"
10045                      "</doc>";
10046   unsigned int i;
10047   const unsigned int max_alloc_count = 30;
10048 
10049   for (i = 0; i < max_alloc_count; i++) {
10050     allocation_count = i;
10051     /* Exercise more code paths with a default handler */
10052     XML_SetDefaultHandler(g_parser, dummy_default_handler);
10053     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10054         != XML_STATUS_ERROR)
10055       break;
10056     /* Resetting the parser is insufficient, because some memory
10057      * allocations are cached within the parser.  Instead we use
10058      * the teardown and setup routines to ensure that we have the
10059      * right sort of parser back in our hands.
10060      */
10061     nsalloc_teardown();
10062     nsalloc_setup();
10063   }
10064   if (i == 0)
10065     fail("Parsing worked despite failing allocations");
10066   else if (i == max_alloc_count)
10067     fail("Parsing failed even at maximum allocation count");
10068 }
10069 END_TEST
10070 
10071 /* Test XML_ParseBuffer interface with namespace and a dicky allocator */
START_TEST(test_nsalloc_parse_buffer)10072 START_TEST(test_nsalloc_parse_buffer) {
10073   const char *text = "<doc>Hello</doc>";
10074   void *buffer;
10075 
10076   /* Try a parse before the start of the world */
10077   /* (Exercises new code path) */
10078   if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_ERROR)
10079     fail("Pre-init XML_ParseBuffer not faulted");
10080   if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_BUFFER)
10081     fail("Pre-init XML_ParseBuffer faulted for wrong reason");
10082 
10083   buffer = XML_GetBuffer(g_parser, 1 /* any small number greater than 0 */);
10084   if (buffer == NULL)
10085     fail("Could not acquire parse buffer");
10086 
10087   allocation_count = 0;
10088   if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_ERROR)
10089     fail("Pre-init XML_ParseBuffer not faulted");
10090   if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_MEMORY)
10091     fail("Pre-init XML_ParseBuffer faulted for wrong reason");
10092 
10093   /* Now with actual memory allocation */
10094   allocation_count = ALLOC_ALWAYS_SUCCEED;
10095   if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_OK)
10096     xml_failure(g_parser);
10097 
10098   /* Check that resuming an unsuspended parser is faulted */
10099   if (XML_ResumeParser(g_parser) != XML_STATUS_ERROR)
10100     fail("Resuming unsuspended parser not faulted");
10101   if (XML_GetErrorCode(g_parser) != XML_ERROR_NOT_SUSPENDED)
10102     xml_failure(g_parser);
10103 
10104   /* Get the parser into suspended state */
10105   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
10106   resumable = XML_TRUE;
10107   buffer = XML_GetBuffer(g_parser, (int)strlen(text));
10108   if (buffer == NULL)
10109     fail("Could not acquire parse buffer");
10110   assert(buffer != NULL);
10111   memcpy(buffer, text, strlen(text));
10112   if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE)
10113       != XML_STATUS_SUSPENDED)
10114     xml_failure(g_parser);
10115   if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE)
10116     xml_failure(g_parser);
10117   if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE)
10118       != XML_STATUS_ERROR)
10119     fail("Suspended XML_ParseBuffer not faulted");
10120   if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED)
10121     xml_failure(g_parser);
10122   if (XML_GetBuffer(g_parser, (int)strlen(text)) != NULL)
10123     fail("Suspended XML_GetBuffer not faulted");
10124 
10125   /* Get it going again and complete the world */
10126   XML_SetCharacterDataHandler(g_parser, NULL);
10127   if (XML_ResumeParser(g_parser) != XML_STATUS_OK)
10128     xml_failure(g_parser);
10129   if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE)
10130       != XML_STATUS_ERROR)
10131     fail("Post-finishing XML_ParseBuffer not faulted");
10132   if (XML_GetErrorCode(g_parser) != XML_ERROR_FINISHED)
10133     xml_failure(g_parser);
10134   if (XML_GetBuffer(g_parser, (int)strlen(text)) != NULL)
10135     fail("Post-finishing XML_GetBuffer not faulted");
10136 }
10137 END_TEST
10138 
10139 /* Check handling of long prefix names (pool growth) */
START_TEST(test_nsalloc_long_prefix)10140 START_TEST(test_nsalloc_long_prefix) {
10141   const char *text
10142       = "<"
10143         /* 64 characters per line */
10144         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10145         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10146         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10147         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10148         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10149         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10150         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10151         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10152         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10153         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10154         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10155         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10156         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10157         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10158         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10159         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10160         ":foo xmlns:"
10161         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10162         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10163         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10164         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10165         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10166         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10167         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10168         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10169         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10170         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10171         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10172         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10173         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10174         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10175         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10176         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10177         "='http://example.org/'>"
10178         "</"
10179         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10180         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10181         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10182         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10183         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10184         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10185         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10186         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10187         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10188         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10189         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10190         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10191         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10192         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10193         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10194         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10195         ":foo>";
10196   int i;
10197   const int max_alloc_count = 40;
10198 
10199   for (i = 0; i < max_alloc_count; i++) {
10200     allocation_count = i;
10201     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10202         != XML_STATUS_ERROR)
10203       break;
10204     /* See comment in test_nsalloc_xmlns() */
10205     nsalloc_teardown();
10206     nsalloc_setup();
10207   }
10208   if (i == 0)
10209     fail("Parsing worked despite failing allocations");
10210   else if (i == max_alloc_count)
10211     fail("Parsing failed even at max allocation count");
10212 }
10213 END_TEST
10214 
10215 /* Check handling of long uri names (pool growth) */
START_TEST(test_nsalloc_long_uri)10216 START_TEST(test_nsalloc_long_uri) {
10217   const char *text
10218       = "<foo:e xmlns:foo='http://example.org/"
10219         /* 64 characters per line */
10220         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10221         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10222         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10223         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10224         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10225         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10226         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10227         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10228         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10229         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10230         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10231         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10232         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10233         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10234         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10235         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10236         "' bar:a='12'\n"
10237         "xmlns:bar='http://example.org/"
10238         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10239         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10240         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10241         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10242         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10243         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10244         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10245         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10246         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10247         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10248         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10249         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10250         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10251         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10252         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10253         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10254         "'>"
10255         "</foo:e>";
10256   int i;
10257   const int max_alloc_count = 40;
10258 
10259   for (i = 0; i < max_alloc_count; i++) {
10260     allocation_count = i;
10261     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10262         != XML_STATUS_ERROR)
10263       break;
10264     /* See comment in test_nsalloc_xmlns() */
10265     nsalloc_teardown();
10266     nsalloc_setup();
10267   }
10268   if (i == 0)
10269     fail("Parsing worked despite failing allocations");
10270   else if (i == max_alloc_count)
10271     fail("Parsing failed even at max allocation count");
10272 }
10273 END_TEST
10274 
10275 /* Test handling of long attribute names with prefixes */
START_TEST(test_nsalloc_long_attr)10276 START_TEST(test_nsalloc_long_attr) {
10277   const char *text
10278       = "<foo:e xmlns:foo='http://example.org/' bar:"
10279         /* 64 characters per line */
10280         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10281         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
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         "='12'\n"
10297         "xmlns:bar='http://example.org/'>"
10298         "</foo:e>";
10299   int i;
10300   const int max_alloc_count = 40;
10301 
10302   for (i = 0; i < max_alloc_count; i++) {
10303     allocation_count = i;
10304     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10305         != XML_STATUS_ERROR)
10306       break;
10307     /* See comment in test_nsalloc_xmlns() */
10308     nsalloc_teardown();
10309     nsalloc_setup();
10310   }
10311   if (i == 0)
10312     fail("Parsing worked despite failing allocations");
10313   else if (i == max_alloc_count)
10314     fail("Parsing failed even at max allocation count");
10315 }
10316 END_TEST
10317 
10318 /* Test handling of an attribute name with a long namespace prefix */
START_TEST(test_nsalloc_long_attr_prefix)10319 START_TEST(test_nsalloc_long_attr_prefix) {
10320   const char *text
10321       = "<foo:e xmlns:foo='http://example.org/' "
10322         /* 64 characters per line */
10323         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10324         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10325         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10326         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10327         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10328         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10329         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10330         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10331         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10332         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10333         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10334         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10335         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10336         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10337         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10338         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10339         ":a='12'\n"
10340         "xmlns:"
10341         /* 64 characters per line */
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         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10358         "='http://example.org/'>"
10359         "</foo:e>";
10360   const XML_Char *elemstr[] = {
10361       /* clang-format off */
10362         XCS("http://example.org/ e foo"),
10363         XCS("http://example.org/ a ")
10364         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10365         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10366         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10367         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10368         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10369         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10370         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10371         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10372         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10373         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10374         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10375         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10376         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10377         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10378         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10379         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10380       /* clang-format on */
10381   };
10382   int i;
10383   const int max_alloc_count = 40;
10384 
10385   for (i = 0; i < max_alloc_count; i++) {
10386     allocation_count = i;
10387     XML_SetReturnNSTriplet(g_parser, XML_TRUE);
10388     XML_SetUserData(g_parser, (void *)elemstr);
10389     XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
10390     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10391         != XML_STATUS_ERROR)
10392       break;
10393     /* See comment in test_nsalloc_xmlns() */
10394     nsalloc_teardown();
10395     nsalloc_setup();
10396   }
10397   if (i == 0)
10398     fail("Parsing worked despite failing allocations");
10399   else if (i == max_alloc_count)
10400     fail("Parsing failed even at max allocation count");
10401 }
10402 END_TEST
10403 
10404 /* Test attribute handling in the face of a dodgy reallocator */
START_TEST(test_nsalloc_realloc_attributes)10405 START_TEST(test_nsalloc_realloc_attributes) {
10406   const char *text = "<foo:e xmlns:foo='http://example.org/' bar:a='12'\n"
10407                      "       xmlns:bar='http://example.org/'>"
10408                      "</foo:e>";
10409   int i;
10410   const int max_realloc_count = 10;
10411 
10412   for (i = 0; i < max_realloc_count; i++) {
10413     reallocation_count = i;
10414     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10415         != XML_STATUS_ERROR)
10416       break;
10417     /* See comment in test_nsalloc_xmlns() */
10418     nsalloc_teardown();
10419     nsalloc_setup();
10420   }
10421   if (i == 0)
10422     fail("Parsing worked despite failing reallocations");
10423   else if (i == max_realloc_count)
10424     fail("Parsing failed at max reallocation count");
10425 }
10426 END_TEST
10427 
10428 /* Test long element names with namespaces under a failing allocator */
START_TEST(test_nsalloc_long_element)10429 START_TEST(test_nsalloc_long_element) {
10430   const char *text
10431       = "<foo:thisisalongenoughelementnametotriggerareallocation\n"
10432         " xmlns:foo='http://example.org/' bar:a='12'\n"
10433         " xmlns:bar='http://example.org/'>"
10434         "</foo:thisisalongenoughelementnametotriggerareallocation>";
10435   const XML_Char *elemstr[]
10436       = {XCS("http://example.org/")
10437              XCS(" thisisalongenoughelementnametotriggerareallocation foo"),
10438          XCS("http://example.org/ a bar")};
10439   int i;
10440   const int max_alloc_count = 30;
10441 
10442   for (i = 0; i < max_alloc_count; i++) {
10443     allocation_count = i;
10444     XML_SetReturnNSTriplet(g_parser, XML_TRUE);
10445     XML_SetUserData(g_parser, (void *)elemstr);
10446     XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
10447     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10448         != XML_STATUS_ERROR)
10449       break;
10450     /* See comment in test_nsalloc_xmlns() */
10451     nsalloc_teardown();
10452     nsalloc_setup();
10453   }
10454   if (i == 0)
10455     fail("Parsing worked despite failing reallocations");
10456   else if (i == max_alloc_count)
10457     fail("Parsing failed at max reallocation count");
10458 }
10459 END_TEST
10460 
10461 /* Test the effects of reallocation failure when reassigning a
10462  * binding.
10463  *
10464  * XML_ParserReset does not free the BINDING structures used by a
10465  * parser, but instead adds them to an internal free list to be reused
10466  * as necessary.  Likewise the URI buffers allocated for the binding
10467  * aren't freed, but kept attached to their existing binding.  If the
10468  * new binding has a longer URI, it will need reallocation.  This test
10469  * provokes that reallocation, and tests the control path if it fails.
10470  */
START_TEST(test_nsalloc_realloc_binding_uri)10471 START_TEST(test_nsalloc_realloc_binding_uri) {
10472   const char *first = "<doc xmlns='http://example.org/'>\n"
10473                       "  <e xmlns='' />\n"
10474                       "</doc>";
10475   const char *second
10476       = "<doc xmlns='http://example.org/long/enough/URI/to/reallocate/'>\n"
10477         "  <e xmlns='' />\n"
10478         "</doc>";
10479   unsigned i;
10480   const unsigned max_realloc_count = 10;
10481 
10482   /* First, do a full parse that will leave bindings around */
10483   if (_XML_Parse_SINGLE_BYTES(g_parser, first, (int)strlen(first), XML_TRUE)
10484       == XML_STATUS_ERROR)
10485     xml_failure(g_parser);
10486 
10487   /* Now repeat with a longer URI and a duff reallocator */
10488   for (i = 0; i < max_realloc_count; i++) {
10489     XML_ParserReset(g_parser, NULL);
10490     reallocation_count = i;
10491     if (_XML_Parse_SINGLE_BYTES(g_parser, second, (int)strlen(second), XML_TRUE)
10492         != XML_STATUS_ERROR)
10493       break;
10494   }
10495   if (i == 0)
10496     fail("Parsing worked despite failing reallocation");
10497   else if (i == max_realloc_count)
10498     fail("Parsing failed at max reallocation count");
10499 }
10500 END_TEST
10501 
10502 /* Check handling of long prefix names (pool growth) */
START_TEST(test_nsalloc_realloc_long_prefix)10503 START_TEST(test_nsalloc_realloc_long_prefix) {
10504   const char *text
10505       = "<"
10506         /* 64 characters per line */
10507         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10508         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10509         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10510         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10511         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10512         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10513         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10514         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10515         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10516         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10517         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10518         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10519         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10520         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10521         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10522         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10523         ":foo xmlns:"
10524         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10525         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10526         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10527         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10528         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10529         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10530         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10531         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10532         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10533         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10534         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10535         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10536         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10537         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10538         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10539         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10540         "='http://example.org/'>"
10541         "</"
10542         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10543         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10544         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10545         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10546         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10547         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10548         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10549         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10550         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10551         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10552         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10553         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10554         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10555         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10556         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10557         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10558         ":foo>";
10559   int i;
10560   const int max_realloc_count = 12;
10561 
10562   for (i = 0; i < max_realloc_count; i++) {
10563     reallocation_count = i;
10564     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10565         != XML_STATUS_ERROR)
10566       break;
10567     /* See comment in test_nsalloc_xmlns() */
10568     nsalloc_teardown();
10569     nsalloc_setup();
10570   }
10571   if (i == 0)
10572     fail("Parsing worked despite failing reallocations");
10573   else if (i == max_realloc_count)
10574     fail("Parsing failed even at max reallocation count");
10575 }
10576 END_TEST
10577 
10578 /* Check handling of even long prefix names (different code path) */
START_TEST(test_nsalloc_realloc_longer_prefix)10579 START_TEST(test_nsalloc_realloc_longer_prefix) {
10580   const char *text
10581       = "<"
10582         /* 64 characters per line */
10583         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10584         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10585         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10586         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10587         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10588         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10589         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10590         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10591         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10592         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10593         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10594         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10595         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10596         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10597         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10598         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10599         "Q:foo xmlns:"
10600         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10601         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10602         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10603         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10604         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10605         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10606         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10607         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10608         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10609         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10610         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10611         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10612         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10613         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10614         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10615         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10616         "Q='http://example.org/'>"
10617         "</"
10618         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10619         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10620         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10621         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10622         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10623         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10624         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10625         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10626         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10627         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10628         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10629         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10630         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10631         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10632         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10633         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10634         "Q:foo>";
10635   int i;
10636   const int max_realloc_count = 12;
10637 
10638   for (i = 0; i < max_realloc_count; i++) {
10639     reallocation_count = i;
10640     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10641         != XML_STATUS_ERROR)
10642       break;
10643     /* See comment in test_nsalloc_xmlns() */
10644     nsalloc_teardown();
10645     nsalloc_setup();
10646   }
10647   if (i == 0)
10648     fail("Parsing worked despite failing reallocations");
10649   else if (i == max_realloc_count)
10650     fail("Parsing failed even at max reallocation count");
10651 }
10652 END_TEST
10653 
START_TEST(test_nsalloc_long_namespace)10654 START_TEST(test_nsalloc_long_namespace) {
10655   const char *text1
10656       = "<"
10657         /* 64 characters per line */
10658         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10659         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10660         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10661         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10662         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10663         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10664         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10665         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10666         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10667         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10668         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10669         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10670         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10671         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10672         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10673         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10674         ":e xmlns:"
10675         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10676         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10677         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10678         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10679         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10680         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10681         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10682         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10683         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10684         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10685         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10686         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10687         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10688         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10689         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10690         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10691         "='http://example.org/'>\n";
10692   const char *text2
10693       = "<"
10694         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10695         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10696         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10697         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10698         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10699         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10700         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10701         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10702         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10703         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10704         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10705         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10706         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10707         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10708         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10709         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10710         ":f "
10711         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10712         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10713         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10714         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10715         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10716         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10717         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10718         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10719         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10720         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10721         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10722         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10723         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10724         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10725         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10726         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10727         ":attr='foo'/>\n"
10728         "</"
10729         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10730         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10731         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10732         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10733         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10734         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10735         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10736         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10737         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10738         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10739         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10740         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10741         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10742         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10743         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10744         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10745         ":e>";
10746   int i;
10747   const int max_alloc_count = 40;
10748 
10749   for (i = 0; i < max_alloc_count; i++) {
10750     allocation_count = i;
10751     if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
10752             != XML_STATUS_ERROR
10753         && _XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2),
10754                                    XML_TRUE)
10755                != XML_STATUS_ERROR)
10756       break;
10757     /* See comment in test_nsalloc_xmlns() */
10758     nsalloc_teardown();
10759     nsalloc_setup();
10760   }
10761   if (i == 0)
10762     fail("Parsing worked despite failing allocations");
10763   else if (i == max_alloc_count)
10764     fail("Parsing failed even at max allocation count");
10765 }
10766 END_TEST
10767 
10768 /* Using a slightly shorter namespace name provokes allocations in
10769  * slightly different places in the code.
10770  */
START_TEST(test_nsalloc_less_long_namespace)10771 START_TEST(test_nsalloc_less_long_namespace) {
10772   const char *text
10773       = "<"
10774         /* 64 characters per line */
10775         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10776         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10777         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10778         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10779         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10780         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10781         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10782         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10783         ":e xmlns:"
10784         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10785         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10786         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10787         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10788         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10789         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10790         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10791         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10792         "='http://example.org/'>\n"
10793         "<"
10794         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10795         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10796         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10797         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10798         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10799         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10800         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10801         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10802         ":f "
10803         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10804         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10805         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10806         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10807         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10808         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10809         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10810         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10811         ":att='foo'/>\n"
10812         "</"
10813         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10814         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10815         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10816         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10817         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10818         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10819         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10820         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10821         ":e>";
10822   int i;
10823   const int max_alloc_count = 40;
10824 
10825   for (i = 0; i < max_alloc_count; i++) {
10826     allocation_count = i;
10827     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10828         != XML_STATUS_ERROR)
10829       break;
10830     /* See comment in test_nsalloc_xmlns() */
10831     nsalloc_teardown();
10832     nsalloc_setup();
10833   }
10834   if (i == 0)
10835     fail("Parsing worked despite failing allocations");
10836   else if (i == max_alloc_count)
10837     fail("Parsing failed even at max allocation count");
10838 }
10839 END_TEST
10840 
START_TEST(test_nsalloc_long_context)10841 START_TEST(test_nsalloc_long_context) {
10842   const char *text
10843       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10844         "  <!ATTLIST doc baz ID #REQUIRED>\n"
10845         "  <!ENTITY en SYSTEM 'bar'>\n"
10846         "]>\n"
10847         "<doc xmlns='http://example.org/"
10848         /* 64 characters per line */
10849         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10850         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10851         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10852         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10853         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10854         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10855         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10856         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10857         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10858         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10859         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10860         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10861         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10862         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10863         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10864         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKL"
10865         "' baz='2'>\n"
10866         "&en;"
10867         "</doc>";
10868   ExtOption options[] = {
10869       {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}};
10870   int i;
10871   const int max_alloc_count = 70;
10872 
10873   for (i = 0; i < max_alloc_count; i++) {
10874     allocation_count = i;
10875     XML_SetUserData(g_parser, options);
10876     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
10877     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
10878     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10879         != XML_STATUS_ERROR)
10880       break;
10881 
10882     /* See comment in test_nsalloc_xmlns() */
10883     nsalloc_teardown();
10884     nsalloc_setup();
10885   }
10886   if (i == 0)
10887     fail("Parsing worked despite failing allocations");
10888   else if (i == max_alloc_count)
10889     fail("Parsing failed even at max allocation count");
10890 }
10891 END_TEST
10892 
10893 /* This function is void; it will throw a fail() on error, so if it
10894  * returns normally it must have succeeded.
10895  */
10896 static void
context_realloc_test(const char * text)10897 context_realloc_test(const char *text) {
10898   ExtOption options[] = {
10899       {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}};
10900   int i;
10901   const int max_realloc_count = 6;
10902 
10903   for (i = 0; i < max_realloc_count; i++) {
10904     reallocation_count = i;
10905     XML_SetUserData(g_parser, options);
10906     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
10907     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
10908     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10909         != XML_STATUS_ERROR)
10910       break;
10911     /* See comment in test_nsalloc_xmlns() */
10912     nsalloc_teardown();
10913     nsalloc_setup();
10914   }
10915   if (i == 0)
10916     fail("Parsing worked despite failing reallocations");
10917   else if (i == max_realloc_count)
10918     fail("Parsing failed even at max reallocation count");
10919 }
10920 
START_TEST(test_nsalloc_realloc_long_context)10921 START_TEST(test_nsalloc_realloc_long_context) {
10922   const char *text
10923       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10924         "  <!ENTITY en SYSTEM 'bar'>\n"
10925         "]>\n"
10926         "<doc xmlns='http://example.org/"
10927         /* 64 characters per line */
10928         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10929         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10930         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10931         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10932         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10933         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10934         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10935         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10936         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10937         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10938         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10939         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10940         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10941         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10942         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10943         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKL"
10944         "'>\n"
10945         "&en;"
10946         "</doc>";
10947 
10948   context_realloc_test(text);
10949 }
10950 END_TEST
10951 
START_TEST(test_nsalloc_realloc_long_context_2)10952 START_TEST(test_nsalloc_realloc_long_context_2) {
10953   const char *text
10954       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10955         "  <!ENTITY en SYSTEM 'bar'>\n"
10956         "]>\n"
10957         "<doc xmlns='http://example.org/"
10958         /* 64 characters per line */
10959         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10960         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10961         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10962         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10963         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10964         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10965         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10966         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10967         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10968         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10969         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10970         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10971         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10972         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10973         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10974         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJK"
10975         "'>\n"
10976         "&en;"
10977         "</doc>";
10978 
10979   context_realloc_test(text);
10980 }
10981 END_TEST
10982 
START_TEST(test_nsalloc_realloc_long_context_3)10983 START_TEST(test_nsalloc_realloc_long_context_3) {
10984   const char *text
10985       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10986         "  <!ENTITY en SYSTEM 'bar'>\n"
10987         "]>\n"
10988         "<doc xmlns='http://example.org/"
10989         /* 64 characters per line */
10990         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10991         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10992         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10993         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10994         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10995         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10996         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10997         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10998         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10999         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11000         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11001         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11002         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11003         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11004         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11005         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGH"
11006         "'>\n"
11007         "&en;"
11008         "</doc>";
11009 
11010   context_realloc_test(text);
11011 }
11012 END_TEST
11013 
START_TEST(test_nsalloc_realloc_long_context_4)11014 START_TEST(test_nsalloc_realloc_long_context_4) {
11015   const char *text
11016       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11017         "  <!ENTITY en SYSTEM 'bar'>\n"
11018         "]>\n"
11019         "<doc xmlns='http://example.org/"
11020         /* 64 characters per line */
11021         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11022         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11023         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11024         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11025         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11026         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11027         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11028         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11029         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11030         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11031         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11032         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11033         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11034         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11035         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11036         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO"
11037         "'>\n"
11038         "&en;"
11039         "</doc>";
11040 
11041   context_realloc_test(text);
11042 }
11043 END_TEST
11044 
START_TEST(test_nsalloc_realloc_long_context_5)11045 START_TEST(test_nsalloc_realloc_long_context_5) {
11046   const char *text
11047       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11048         "  <!ENTITY en SYSTEM 'bar'>\n"
11049         "]>\n"
11050         "<doc xmlns='http://example.org/"
11051         /* 64 characters per line */
11052         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11053         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11054         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11055         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11056         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11057         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11058         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11059         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11060         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11061         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11062         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11063         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11064         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11065         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11066         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11067         "ABC"
11068         "'>\n"
11069         "&en;"
11070         "</doc>";
11071 
11072   context_realloc_test(text);
11073 }
11074 END_TEST
11075 
START_TEST(test_nsalloc_realloc_long_context_6)11076 START_TEST(test_nsalloc_realloc_long_context_6) {
11077   const char *text
11078       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11079         "  <!ENTITY en SYSTEM 'bar'>\n"
11080         "]>\n"
11081         "<doc xmlns='http://example.org/"
11082         /* 64 characters per line */
11083         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11084         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11085         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11086         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11087         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11088         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11089         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11090         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11091         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11092         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11093         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11094         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11095         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11096         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11097         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
11098         "'>\n"
11099         "&en;"
11100         "</doc>";
11101 
11102   context_realloc_test(text);
11103 }
11104 END_TEST
11105 
START_TEST(test_nsalloc_realloc_long_context_7)11106 START_TEST(test_nsalloc_realloc_long_context_7) {
11107   const char *text
11108       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11109         "  <!ENTITY en SYSTEM 'bar'>\n"
11110         "]>\n"
11111         "<doc xmlns='http://example.org/"
11112         /* 64 characters per line */
11113         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11114         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11115         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11116         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11117         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11118         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11119         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11120         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11121         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11122         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11123         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11124         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11125         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11126         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11127         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11128         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLM"
11129         "'>\n"
11130         "&en;"
11131         "</doc>";
11132 
11133   context_realloc_test(text);
11134 }
11135 END_TEST
11136 
START_TEST(test_nsalloc_realloc_long_ge_name)11137 START_TEST(test_nsalloc_realloc_long_ge_name) {
11138   const char *text
11139       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11140         "  <!ENTITY "
11141         /* 64 characters per line */
11142         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11143         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11144         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11145         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11146         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11147         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11148         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11149         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11150         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11151         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11152         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11153         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11154         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11155         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11156         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11157         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11158         " SYSTEM 'bar'>\n"
11159         "]>\n"
11160         "<doc xmlns='http://example.org/baz'>\n"
11161         "&"
11162         /* 64 characters per line */
11163         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11164         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11165         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11166         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11167         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11168         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11169         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11170         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11171         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11172         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11173         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11174         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11175         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11176         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11177         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11178         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11179         ";"
11180         "</doc>";
11181   ExtOption options[] = {
11182       {XCS("foo"), "<!ELEMENT el EMPTY>"}, {XCS("bar"), "<el/>"}, {NULL, NULL}};
11183   int i;
11184   const int max_realloc_count = 10;
11185 
11186   for (i = 0; i < max_realloc_count; i++) {
11187     reallocation_count = i;
11188     XML_SetUserData(g_parser, options);
11189     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11190     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11191     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
11192         != XML_STATUS_ERROR)
11193       break;
11194     /* See comment in test_nsalloc_xmlns() */
11195     nsalloc_teardown();
11196     nsalloc_setup();
11197   }
11198   if (i == 0)
11199     fail("Parsing worked despite failing reallocations");
11200   else if (i == max_realloc_count)
11201     fail("Parsing failed even at max reallocation count");
11202 }
11203 END_TEST
11204 
11205 /* Test that when a namespace is passed through the context mechanism
11206  * to an external entity parser, the parsers handle reallocation
11207  * failures correctly.  The prefix is exactly the right length to
11208  * provoke particular uncommon code paths.
11209  */
START_TEST(test_nsalloc_realloc_long_context_in_dtd)11210 START_TEST(test_nsalloc_realloc_long_context_in_dtd) {
11211   const char *text1
11212       = "<!DOCTYPE "
11213         /* 64 characters per line */
11214         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11215         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11216         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11217         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11218         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11219         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11220         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11221         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11222         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11223         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11224         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11225         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11226         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11227         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11228         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11229         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11230         ":doc [\n"
11231         "  <!ENTITY First SYSTEM 'foo/First'>\n"
11232         "]>\n"
11233         "<"
11234         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11235         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11236         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11237         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11238         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11239         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11240         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11241         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11242         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11243         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11244         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11245         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11246         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11247         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11248         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11249         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11250         ":doc xmlns:"
11251         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11252         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11253         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11254         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11255         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11256         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11257         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11258         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11259         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11260         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11261         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11262         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11263         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11264         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11265         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11266         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11267         "='foo/Second'>&First;";
11268   const char *text2
11269       = "</"
11270         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11271         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11272         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11273         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11274         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11275         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11276         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11277         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11278         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11279         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11280         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11281         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11282         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11283         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11284         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11285         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11286         ":doc>";
11287   ExtOption options[] = {{XCS("foo/First"), "Hello world"}, {NULL, NULL}};
11288   int i;
11289   const int max_realloc_count = 20;
11290 
11291   for (i = 0; i < max_realloc_count; i++) {
11292     reallocation_count = i;
11293     XML_SetUserData(g_parser, options);
11294     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11295     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11296     if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
11297             != XML_STATUS_ERROR
11298         && _XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2),
11299                                    XML_TRUE)
11300                != XML_STATUS_ERROR)
11301       break;
11302     /* See comment in test_nsalloc_xmlns() */
11303     nsalloc_teardown();
11304     nsalloc_setup();
11305   }
11306   if (i == 0)
11307     fail("Parsing worked despite failing reallocations");
11308   else if (i == max_realloc_count)
11309     fail("Parsing failed even at max reallocation count");
11310 }
11311 END_TEST
11312 
START_TEST(test_nsalloc_long_default_in_ext)11313 START_TEST(test_nsalloc_long_default_in_ext) {
11314   const char *text
11315       = "<!DOCTYPE doc [\n"
11316         "  <!ATTLIST e a1 CDATA '"
11317         /* 64 characters per line */
11318         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11319         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11320         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11321         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11322         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11323         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11324         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11325         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11326         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11327         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11328         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11329         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11330         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11331         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11332         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11333         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11334         "'>\n"
11335         "  <!ENTITY x SYSTEM 'foo'>\n"
11336         "]>\n"
11337         "<doc>&x;</doc>";
11338   ExtOption options[] = {{XCS("foo"), "<e/>"}, {NULL, NULL}};
11339   int i;
11340   const int max_alloc_count = 50;
11341 
11342   for (i = 0; i < max_alloc_count; i++) {
11343     allocation_count = i;
11344     XML_SetUserData(g_parser, options);
11345     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11346     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11347     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
11348         != XML_STATUS_ERROR)
11349       break;
11350 
11351     /* See comment in test_nsalloc_xmlns() */
11352     nsalloc_teardown();
11353     nsalloc_setup();
11354   }
11355   if (i == 0)
11356     fail("Parsing worked despite failing allocations");
11357   else if (i == max_alloc_count)
11358     fail("Parsing failed even at max allocation count");
11359 }
11360 END_TEST
11361 
START_TEST(test_nsalloc_long_systemid_in_ext)11362 START_TEST(test_nsalloc_long_systemid_in_ext) {
11363   const char *text
11364       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11365         "  <!ENTITY en SYSTEM '"
11366         /* 64 characters per line */
11367         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11368         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11369         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11370         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11371         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11372         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11373         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11374         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11375         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11376         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11377         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11378         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11379         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11380         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11381         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11382         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11383         "'>\n"
11384         "]>\n"
11385         "<doc>&en;</doc>";
11386   ExtOption options[] = {
11387       {XCS("foo"), "<!ELEMENT e EMPTY>"},
11388       {/* clang-format off */
11389             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11390             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11391             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11392             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11393             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11394             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11395             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11396             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11397             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11398             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11399             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11400             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11401             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11402             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11403             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11404             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"),
11405        /* clang-format on */
11406        "<e/>"},
11407       {NULL, NULL}};
11408   int i;
11409   const int max_alloc_count = 55;
11410 
11411   for (i = 0; i < max_alloc_count; i++) {
11412     allocation_count = i;
11413     XML_SetUserData(g_parser, options);
11414     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11415     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11416     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
11417         != XML_STATUS_ERROR)
11418       break;
11419 
11420     /* See comment in test_nsalloc_xmlns() */
11421     nsalloc_teardown();
11422     nsalloc_setup();
11423   }
11424   if (i == 0)
11425     fail("Parsing worked despite failing allocations");
11426   else if (i == max_alloc_count)
11427     fail("Parsing failed even at max allocation count");
11428 }
11429 END_TEST
11430 
11431 /* Test the effects of allocation failure on parsing an element in a
11432  * namespace.  Based on test_nsalloc_long_context.
11433  */
START_TEST(test_nsalloc_prefixed_element)11434 START_TEST(test_nsalloc_prefixed_element) {
11435   const char *text = "<!DOCTYPE pfx:element SYSTEM 'foo' [\n"
11436                      "  <!ATTLIST pfx:element baz ID #REQUIRED>\n"
11437                      "  <!ENTITY en SYSTEM 'bar'>\n"
11438                      "]>\n"
11439                      "<pfx:element xmlns:pfx='http://example.org/' baz='2'>\n"
11440                      "&en;"
11441                      "</pfx:element>";
11442   ExtOption options[] = {
11443       {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}};
11444   int i;
11445   const int max_alloc_count = 70;
11446 
11447   for (i = 0; i < max_alloc_count; i++) {
11448     allocation_count = i;
11449     XML_SetUserData(g_parser, options);
11450     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11451     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11452     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
11453         != XML_STATUS_ERROR)
11454       break;
11455 
11456     /* See comment in test_nsalloc_xmlns() */
11457     nsalloc_teardown();
11458     nsalloc_setup();
11459   }
11460   if (i == 0)
11461     fail("Success despite failing allocator");
11462   else if (i == max_alloc_count)
11463     fail("Failed even at full allocation count");
11464 }
11465 END_TEST
11466 
11467 #if defined(XML_DTD)
11468 typedef enum XML_Status (*XmlParseFunction)(XML_Parser, const char *, int, int);
11469 
11470 struct AccountingTestCase {
11471   const char *primaryText;
11472   const char *firstExternalText;  /* often NULL */
11473   const char *secondExternalText; /* often NULL */
11474   const unsigned long long expectedCountBytesIndirectExtra;
11475   XML_Bool singleBytesWanted;
11476 };
11477 
11478 static int
accounting_external_entity_ref_handler(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)11479 accounting_external_entity_ref_handler(XML_Parser parser,
11480                                        const XML_Char *context,
11481                                        const XML_Char *base,
11482                                        const XML_Char *systemId,
11483                                        const XML_Char *publicId) {
11484   UNUSED_P(context);
11485   UNUSED_P(base);
11486   UNUSED_P(publicId);
11487 
11488   const struct AccountingTestCase *const testCase
11489       = (const struct AccountingTestCase *)XML_GetUserData(parser);
11490 
11491   const char *externalText = NULL;
11492   if (xcstrcmp(systemId, XCS("first.ent")) == 0) {
11493     externalText = testCase->firstExternalText;
11494   } else if (xcstrcmp(systemId, XCS("second.ent")) == 0) {
11495     externalText = testCase->secondExternalText;
11496   } else {
11497     assert(! "systemId is neither \"first.ent\" nor \"second.ent\"");
11498   }
11499   assert(externalText);
11500 
11501   XML_Parser entParser = XML_ExternalEntityParserCreate(parser, context, 0);
11502   assert(entParser);
11503 
11504   const XmlParseFunction xmlParseFunction
11505       = testCase->singleBytesWanted ? _XML_Parse_SINGLE_BYTES : XML_Parse;
11506 
11507   const enum XML_Status status = xmlParseFunction(
11508       entParser, externalText, (int)strlen(externalText), XML_TRUE);
11509 
11510   XML_ParserFree(entParser);
11511   return status;
11512 }
11513 
START_TEST(test_accounting_precision)11514 START_TEST(test_accounting_precision) {
11515   const XML_Bool filled_later = XML_TRUE; /* value is arbitrary */
11516   struct AccountingTestCase cases[] = {
11517       {"<e/>", NULL, NULL, 0, 0},
11518       {"<e></e>", NULL, NULL, 0, 0},
11519 
11520       /* Attributes */
11521       {"<e k1=\"v2\" k2=\"v2\"/>", NULL, NULL, 0, filled_later},
11522       {"<e k1=\"v2\" k2=\"v2\"></e>", NULL, NULL, 0, 0},
11523       {"<p:e xmlns:p=\"https://domain.invalid/\" />", NULL, NULL, 0,
11524        filled_later},
11525       {"<e k=\"&amp;&apos;&gt;&lt;&quot;\" />", NULL, NULL,
11526        sizeof(XML_Char) * 5 /* number of predefined entities */, filled_later},
11527       {"<e1 xmlns='https://example.org/'>\n"
11528        "  <e2 xmlns=''/>\n"
11529        "</e1>",
11530        NULL, NULL, 0, filled_later},
11531 
11532       /* Text */
11533       {"<e>text</e>", NULL, NULL, 0, filled_later},
11534       {"<e1><e2>text1<e3/>text2</e2></e1>", NULL, NULL, 0, filled_later},
11535       {"<e>&amp;&apos;&gt;&lt;&quot;</e>", NULL, NULL,
11536        sizeof(XML_Char) * 5 /* number of predefined entities */, filled_later},
11537       {"<e>&#65;&#41;</e>", NULL, NULL, 0, filled_later},
11538 
11539       /* Prolog */
11540       {"<?xml version=\"1.0\"?><root/>", NULL, NULL, 0, filled_later},
11541 
11542       /* Whitespace */
11543       {"  <e1>  <e2>  </e2>  </e1>  ", NULL, NULL, 0, filled_later},
11544       {"<e1  ><e2  /></e1  >", NULL, NULL, 0, filled_later},
11545       {"<e1><e2 k = \"v\"/><e3 k = 'v'/></e1>", NULL, NULL, 0, filled_later},
11546 
11547       /* Comments */
11548       {"<!-- Comment --><e><!-- Comment --></e>", NULL, NULL, 0, filled_later},
11549 
11550       /* Processing instructions */
11551       {"<?xml-stylesheet type=\"text/xsl\" href=\"https://domain.invalid/\" media=\"all\"?><e/>",
11552        NULL, NULL, 0, filled_later},
11553       {"<?pi0?><?pi1 ?><?pi2  ?><!DOCTYPE r SYSTEM 'first.ent'><r/>",
11554        "<?pi3?><!ENTITY % e1 SYSTEM 'second.ent'><?pi4?>%e1;<?pi5?>", "<?pi6?>",
11555        0, filled_later},
11556 
11557       /* CDATA */
11558       {"<e><![CDATA[one two three]]></e>", NULL, NULL, 0, filled_later},
11559       /* The following is the essence of this OSS-Fuzz finding:
11560          https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=34302
11561          https://oss-fuzz.com/testcase-detail/4860575394955264
11562       */
11563       {"<!DOCTYPE r [\n"
11564        "<!ENTITY e \"111<![CDATA[2 <= 2]]>333\">\n"
11565        "]>\n"
11566        "<r>&e;</r>\n",
11567        NULL, NULL, sizeof(XML_Char) * strlen("111<![CDATA[2 <= 2]]>333"),
11568        filled_later},
11569 
11570       /* Conditional sections */
11571       {"<!DOCTYPE r [\n"
11572        "<!ENTITY % draft 'INCLUDE'>\n"
11573        "<!ENTITY % final 'IGNORE'>\n"
11574        "<!ENTITY % import SYSTEM \"first.ent\">\n"
11575        "%import;\n"
11576        "]>\n"
11577        "<r/>\n",
11578        "<![%draft;[<!--1-->]]>\n"
11579        "<![%final;[<!--22-->]]>",
11580        NULL, sizeof(XML_Char) * (strlen("INCLUDE") + strlen("IGNORE")),
11581        filled_later},
11582 
11583       /* General entities */
11584       {"<!DOCTYPE root [\n"
11585        "<!ENTITY nine \"123456789\">\n"
11586        "]>\n"
11587        "<root>&nine;</root>",
11588        NULL, NULL, sizeof(XML_Char) * strlen("123456789"), filled_later},
11589       {"<!DOCTYPE root [\n"
11590        "<!ENTITY nine \"123456789\">\n"
11591        "]>\n"
11592        "<root k1=\"&nine;\"/>",
11593        NULL, NULL, sizeof(XML_Char) * strlen("123456789"), filled_later},
11594       {"<!DOCTYPE root [\n"
11595        "<!ENTITY nine \"123456789\">\n"
11596        "<!ENTITY nine2 \"&nine;&nine;\">\n"
11597        "]>\n"
11598        "<root>&nine2;&nine2;&nine2;</root>",
11599        NULL, NULL,
11600        sizeof(XML_Char) * 3 /* calls to &nine2; */ * 2 /* calls to &nine; */
11601            * (strlen("&nine;") + strlen("123456789")),
11602        filled_later},
11603       {"<!DOCTYPE r [\n"
11604        "  <!ENTITY five SYSTEM 'first.ent'>\n"
11605        "]>\n"
11606        "<r>&five;</r>",
11607        "12345", NULL, 0, filled_later},
11608 
11609       /* Parameter entities */
11610       {"<!DOCTYPE r [\n"
11611        "<!ENTITY % comment \"<!---->\">\n"
11612        "%comment;\n"
11613        "]>\n"
11614        "<r/>",
11615        NULL, NULL, sizeof(XML_Char) * strlen("<!---->"), filled_later},
11616       {"<!DOCTYPE r [\n"
11617        "<!ENTITY % ninedef \"&#60;!ENTITY nine &#34;123456789&#34;&#62;\">\n"
11618        "%ninedef;\n"
11619        "]>\n"
11620        "<r>&nine;</r>",
11621        NULL, NULL,
11622        sizeof(XML_Char)
11623            * (strlen("<!ENTITY nine \"123456789\">") + strlen("123456789")),
11624        filled_later},
11625       {"<!DOCTYPE r [\n"
11626        "<!ENTITY % comment \"<!--1-->\">\n"
11627        "<!ENTITY % comment2 \"&#37;comment;<!--22-->&#37;comment;\">\n"
11628        "%comment2;\n"
11629        "]>\n"
11630        "<r/>\n",
11631        NULL, NULL,
11632        sizeof(XML_Char)
11633            * (strlen("%comment;<!--22-->%comment;") + 2 * strlen("<!--1-->")),
11634        filled_later},
11635       {"<!DOCTYPE r [\n"
11636        "  <!ENTITY % five \"12345\">\n"
11637        "  <!ENTITY % five2def \"&#60;!ENTITY five2 &#34;[&#37;five;][&#37;five;]]]]&#34;&#62;\">\n"
11638        "  %five2def;\n"
11639        "]>\n"
11640        "<r>&five2;</r>",
11641        NULL, NULL, /* from "%five2def;": */
11642        sizeof(XML_Char)
11643            * (strlen("<!ENTITY five2 \"[%five;][%five;]]]]\">")
11644               + 2 /* calls to "%five;" */ * strlen("12345")
11645               + /* from "&five2;": */ strlen("[12345][12345]]]]")),
11646        filled_later},
11647       {"<!DOCTYPE r SYSTEM \"first.ent\">\n"
11648        "<r/>",
11649        "<!ENTITY % comment '<!--1-->'>\n"
11650        "<!ENTITY % comment2 '<!--22-->%comment;<!--22-->%comment;<!--22-->'>\n"
11651        "%comment2;",
11652        NULL,
11653        sizeof(XML_Char)
11654            * (strlen("<!--22-->%comment;<!--22-->%comment;<!--22-->")
11655               + 2 /* calls to "%comment;" */ * strlen("<!---->")),
11656        filled_later},
11657       {"<!DOCTYPE r SYSTEM 'first.ent'>\n"
11658        "<r/>",
11659        "<!ENTITY % e1 PUBLIC 'foo' 'second.ent'>\n"
11660        "<!ENTITY % e2 '<!--22-->%e1;<!--22-->'>\n"
11661        "%e2;\n",
11662        "<!--1-->", sizeof(XML_Char) * strlen("<!--22--><!--1--><!--22-->"),
11663        filled_later},
11664       {
11665           "<!DOCTYPE r SYSTEM 'first.ent'>\n"
11666           "<r/>",
11667           "<!ENTITY % e1 SYSTEM 'second.ent'>\n"
11668           "<!ENTITY % e2 '%e1;'>",
11669           "<?xml version='1.0' encoding='utf-8'?>\n"
11670           "hello\n"
11671           "xml" /* without trailing newline! */,
11672           0,
11673           filled_later,
11674       },
11675       {
11676           "<!DOCTYPE r SYSTEM 'first.ent'>\n"
11677           "<r/>",
11678           "<!ENTITY % e1 SYSTEM 'second.ent'>\n"
11679           "<!ENTITY % e2 '%e1;'>",
11680           "<?xml version='1.0' encoding='utf-8'?>\n"
11681           "hello\n"
11682           "xml\n" /* with trailing newline! */,
11683           0,
11684           filled_later,
11685       },
11686       {"<!DOCTYPE doc SYSTEM 'first.ent'>\n"
11687        "<doc></doc>\n",
11688        "<!ELEMENT doc EMPTY>\n"
11689        "<!ENTITY % e1 SYSTEM 'second.ent'>\n"
11690        "<!ENTITY % e2 '%e1;'>\n"
11691        "%e1;\n",
11692        "\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>" /* UTF-8 BOM */,
11693        strlen("\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>"), filled_later},
11694       {"<!DOCTYPE r [\n"
11695        "  <!ENTITY five SYSTEM 'first.ent'>\n"
11696        "]>\n"
11697        "<r>&five;</r>",
11698        "\xEF\xBB\xBF" /* UTF-8 BOM */, NULL, 0, filled_later},
11699   };
11700 
11701   const size_t countCases = sizeof(cases) / sizeof(cases[0]);
11702   size_t u = 0;
11703   for (; u < countCases; u++) {
11704     size_t v = 0;
11705     for (; v < 2; v++) {
11706       const XML_Bool singleBytesWanted = (v == 0) ? XML_FALSE : XML_TRUE;
11707       const unsigned long long expectedCountBytesDirect
11708           = strlen(cases[u].primaryText);
11709       const unsigned long long expectedCountBytesIndirect
11710           = (cases[u].firstExternalText ? strlen(cases[u].firstExternalText)
11711                                         : 0)
11712             + (cases[u].secondExternalText ? strlen(cases[u].secondExternalText)
11713                                            : 0)
11714             + cases[u].expectedCountBytesIndirectExtra;
11715 
11716       XML_Parser parser = XML_ParserCreate(NULL);
11717       XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11718       if (cases[u].firstExternalText) {
11719         XML_SetExternalEntityRefHandler(parser,
11720                                         accounting_external_entity_ref_handler);
11721         XML_SetUserData(parser, (void *)&cases[u]);
11722         cases[u].singleBytesWanted = singleBytesWanted;
11723       }
11724 
11725       const XmlParseFunction xmlParseFunction
11726           = singleBytesWanted ? _XML_Parse_SINGLE_BYTES : XML_Parse;
11727 
11728       enum XML_Status status
11729           = xmlParseFunction(parser, cases[u].primaryText,
11730                              (int)strlen(cases[u].primaryText), XML_TRUE);
11731       if (status != XML_STATUS_OK) {
11732         _xml_failure(parser, __FILE__, __LINE__);
11733       }
11734 
11735       const unsigned long long actualCountBytesDirect
11736           = testingAccountingGetCountBytesDirect(parser);
11737       const unsigned long long actualCountBytesIndirect
11738           = testingAccountingGetCountBytesIndirect(parser);
11739 
11740       XML_ParserFree(parser);
11741 
11742       if (actualCountBytesDirect != expectedCountBytesDirect) {
11743         fprintf(
11744             stderr,
11745             "Document " EXPAT_FMT_SIZE_T("") " of " EXPAT_FMT_SIZE_T("") ", %s: Expected " EXPAT_FMT_ULL(
11746                 "") " count direct bytes, got " EXPAT_FMT_ULL("") " instead.\n",
11747             u + 1, countCases, singleBytesWanted ? "single bytes" : "chunks",
11748             expectedCountBytesDirect, actualCountBytesDirect);
11749         fail("Count of direct bytes is off");
11750       }
11751 
11752       if (actualCountBytesIndirect != expectedCountBytesIndirect) {
11753         fprintf(
11754             stderr,
11755             "Document " EXPAT_FMT_SIZE_T("") " of " EXPAT_FMT_SIZE_T("") ", %s: Expected " EXPAT_FMT_ULL(
11756                 "") " count indirect bytes, got " EXPAT_FMT_ULL("") " instead.\n",
11757             u + 1, countCases, singleBytesWanted ? "single bytes" : "chunks",
11758             expectedCountBytesIndirect, actualCountBytesIndirect);
11759         fail("Count of indirect bytes is off");
11760       }
11761     }
11762   }
11763 }
11764 END_TEST
11765 
11766 static float
portableNAN()11767 portableNAN() {
11768   return strtof("nan", NULL);
11769 }
11770 
11771 static float
portableINFINITY()11772 portableINFINITY() {
11773   return strtof("infinity", NULL);
11774 }
11775 
START_TEST(test_billion_laughs_attack_protection_api)11776 START_TEST(test_billion_laughs_attack_protection_api) {
11777   XML_Parser parserWithoutParent = XML_ParserCreate(NULL);
11778   XML_Parser parserWithParent
11779       = XML_ExternalEntityParserCreate(parserWithoutParent, NULL, NULL);
11780   if (parserWithoutParent == NULL)
11781     fail("parserWithoutParent is NULL");
11782   if (parserWithParent == NULL)
11783     fail("parserWithParent is NULL");
11784 
11785   // XML_SetBillionLaughsAttackProtectionMaximumAmplification, error cases
11786   if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(NULL, 123.0f)
11787       == XML_TRUE)
11788     fail("Call with NULL parser is NOT supposed to succeed");
11789   if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(parserWithParent,
11790                                                                123.0f)
11791       == XML_TRUE)
11792     fail("Call with non-root parser is NOT supposed to succeed");
11793   if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
11794           parserWithoutParent, portableNAN())
11795       == XML_TRUE)
11796     fail("Call with NaN limit is NOT supposed to succeed");
11797   if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
11798           parserWithoutParent, -1.0f)
11799       == XML_TRUE)
11800     fail("Call with negative limit is NOT supposed to succeed");
11801   if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
11802           parserWithoutParent, 0.9f)
11803       == XML_TRUE)
11804     fail("Call with positive limit <1.0 is NOT supposed to succeed");
11805 
11806   // XML_SetBillionLaughsAttackProtectionMaximumAmplification, success cases
11807   if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
11808           parserWithoutParent, 1.0f)
11809       == XML_FALSE)
11810     fail("Call with positive limit >=1.0 is supposed to succeed");
11811   if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
11812           parserWithoutParent, 123456.789f)
11813       == XML_FALSE)
11814     fail("Call with positive limit >=1.0 is supposed to succeed");
11815   if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
11816           parserWithoutParent, portableINFINITY())
11817       == XML_FALSE)
11818     fail("Call with positive limit >=1.0 is supposed to succeed");
11819 
11820   // XML_SetBillionLaughsAttackProtectionActivationThreshold, error cases
11821   if (XML_SetBillionLaughsAttackProtectionActivationThreshold(NULL, 123)
11822       == XML_TRUE)
11823     fail("Call with NULL parser is NOT supposed to succeed");
11824   if (XML_SetBillionLaughsAttackProtectionActivationThreshold(parserWithParent,
11825                                                               123)
11826       == XML_TRUE)
11827     fail("Call with non-root parser is NOT supposed to succeed");
11828 
11829   // XML_SetBillionLaughsAttackProtectionActivationThreshold, success cases
11830   if (XML_SetBillionLaughsAttackProtectionActivationThreshold(
11831           parserWithoutParent, 123)
11832       == XML_FALSE)
11833     fail("Call with non-NULL parentless parser is supposed to succeed");
11834 
11835   XML_ParserFree(parserWithParent);
11836   XML_ParserFree(parserWithoutParent);
11837 }
11838 END_TEST
11839 
START_TEST(test_helper_unsigned_char_to_printable)11840 START_TEST(test_helper_unsigned_char_to_printable) {
11841   // Smoke test
11842   unsigned char uc = 0;
11843   for (; uc < (unsigned char)-1; uc++) {
11844     const char *const printable = unsignedCharToPrintable(uc);
11845     if (printable == NULL)
11846       fail("unsignedCharToPrintable returned NULL");
11847     if (strlen(printable) < (size_t)1)
11848       fail("unsignedCharToPrintable returned empty string");
11849   }
11850 
11851   // Two concrete samples
11852   if (strcmp(unsignedCharToPrintable('A'), "A") != 0)
11853     fail("unsignedCharToPrintable result mistaken");
11854   if (strcmp(unsignedCharToPrintable('\\'), "\\\\") != 0)
11855     fail("unsignedCharToPrintable result mistaken");
11856 }
11857 END_TEST
11858 #endif // defined(XML_DTD)
11859 
11860 static Suite *
make_suite(void)11861 make_suite(void) {
11862   Suite *s = suite_create("basic");
11863   TCase *tc_basic = tcase_create("basic tests");
11864   TCase *tc_namespace = tcase_create("XML namespaces");
11865   TCase *tc_misc = tcase_create("miscellaneous tests");
11866   TCase *tc_alloc = tcase_create("allocation tests");
11867   TCase *tc_nsalloc = tcase_create("namespace allocation tests");
11868 #if defined(XML_DTD)
11869   TCase *tc_accounting = tcase_create("accounting tests");
11870 #endif
11871 
11872   suite_add_tcase(s, tc_basic);
11873   tcase_add_checked_fixture(tc_basic, basic_setup, basic_teardown);
11874   tcase_add_test(tc_basic, test_nul_byte);
11875   tcase_add_test(tc_basic, test_u0000_char);
11876   tcase_add_test(tc_basic, test_siphash_self);
11877   tcase_add_test(tc_basic, test_siphash_spec);
11878   tcase_add_test(tc_basic, test_bom_utf8);
11879   tcase_add_test(tc_basic, test_bom_utf16_be);
11880   tcase_add_test(tc_basic, test_bom_utf16_le);
11881   tcase_add_test(tc_basic, test_nobom_utf16_le);
11882   tcase_add_test(tc_basic, test_illegal_utf8);
11883   tcase_add_test(tc_basic, test_utf8_auto_align);
11884   tcase_add_test(tc_basic, test_utf16);
11885   tcase_add_test(tc_basic, test_utf16_le_epilog_newline);
11886   tcase_add_test(tc_basic, test_not_utf16);
11887   tcase_add_test(tc_basic, test_bad_encoding);
11888   tcase_add_test(tc_basic, test_latin1_umlauts);
11889   tcase_add_test(tc_basic, test_long_utf8_character);
11890   tcase_add_test(tc_basic, test_long_latin1_attribute);
11891   tcase_add_test(tc_basic, test_long_ascii_attribute);
11892   /* Regression test for SF bug #491986. */
11893   tcase_add_test(tc_basic, test_danish_latin1);
11894   /* Regression test for SF bug #514281. */
11895   tcase_add_test(tc_basic, test_french_charref_hexidecimal);
11896   tcase_add_test(tc_basic, test_french_charref_decimal);
11897   tcase_add_test(tc_basic, test_french_latin1);
11898   tcase_add_test(tc_basic, test_french_utf8);
11899   tcase_add_test(tc_basic, test_utf8_false_rejection);
11900   tcase_add_test(tc_basic, test_line_number_after_parse);
11901   tcase_add_test(tc_basic, test_column_number_after_parse);
11902   tcase_add_test(tc_basic, test_line_and_column_numbers_inside_handlers);
11903   tcase_add_test(tc_basic, test_line_number_after_error);
11904   tcase_add_test(tc_basic, test_column_number_after_error);
11905   tcase_add_test(tc_basic, test_really_long_lines);
11906   tcase_add_test(tc_basic, test_really_long_encoded_lines);
11907   tcase_add_test(tc_basic, test_end_element_events);
11908   tcase_add_test(tc_basic, test_attr_whitespace_normalization);
11909   tcase_add_test(tc_basic, test_xmldecl_misplaced);
11910   tcase_add_test(tc_basic, test_xmldecl_invalid);
11911   tcase_add_test(tc_basic, test_xmldecl_missing_attr);
11912   tcase_add_test(tc_basic, test_xmldecl_missing_value);
11913   tcase_add_test(tc_basic, test_unknown_encoding_internal_entity);
11914   tcase_add_test(tc_basic, test_unrecognised_encoding_internal_entity);
11915   tcase_add_test(tc_basic, test_wfc_undeclared_entity_unread_external_subset);
11916   tcase_add_test(tc_basic, test_wfc_undeclared_entity_no_external_subset);
11917   tcase_add_test(tc_basic, test_wfc_undeclared_entity_standalone);
11918   tcase_add_test(tc_basic, test_wfc_undeclared_entity_with_external_subset);
11919   tcase_add_test(tc_basic, test_not_standalone_handler_reject);
11920   tcase_add_test(tc_basic, test_not_standalone_handler_accept);
11921   tcase_add_test(tc_basic,
11922                  test_wfc_undeclared_entity_with_external_subset_standalone);
11923   tcase_add_test(tc_basic, test_entity_with_external_subset_unless_standalone);
11924   tcase_add_test(tc_basic, test_wfc_no_recursive_entity_refs);
11925   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_set_encoding);
11926   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_no_handler);
11927   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_set_bom);
11928   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_bad_encoding);
11929   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_bad_encoding_2);
11930   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_invalid_parse);
11931   tcase_add_test__ifdef_xml_dtd(tc_basic,
11932                                 test_ext_entity_invalid_suspended_parse);
11933   tcase_add_test(tc_basic, test_dtd_default_handling);
11934   tcase_add_test(tc_basic, test_dtd_attr_handling);
11935   tcase_add_test(tc_basic, test_empty_ns_without_namespaces);
11936   tcase_add_test(tc_basic, test_ns_in_attribute_default_without_namespaces);
11937   tcase_add_test(tc_basic, test_stop_parser_between_char_data_calls);
11938   tcase_add_test(tc_basic, test_suspend_parser_between_char_data_calls);
11939   tcase_add_test(tc_basic, test_repeated_stop_parser_between_char_data_calls);
11940   tcase_add_test(tc_basic, test_good_cdata_ascii);
11941   tcase_add_test(tc_basic, test_good_cdata_utf16);
11942   tcase_add_test(tc_basic, test_good_cdata_utf16_le);
11943   tcase_add_test(tc_basic, test_long_cdata_utf16);
11944   tcase_add_test(tc_basic, test_multichar_cdata_utf16);
11945   tcase_add_test(tc_basic, test_utf16_bad_surrogate_pair);
11946   tcase_add_test(tc_basic, test_bad_cdata);
11947   tcase_add_test(tc_basic, test_bad_cdata_utf16);
11948   tcase_add_test(tc_basic, test_stop_parser_between_cdata_calls);
11949   tcase_add_test(tc_basic, test_suspend_parser_between_cdata_calls);
11950   tcase_add_test(tc_basic, test_memory_allocation);
11951   tcase_add_test(tc_basic, test_default_current);
11952   tcase_add_test(tc_basic, test_dtd_elements);
11953   tcase_add_test(tc_basic, test_dtd_elements_nesting);
11954   tcase_add_test__ifdef_xml_dtd(tc_basic, test_set_foreign_dtd);
11955   tcase_add_test__ifdef_xml_dtd(tc_basic, test_foreign_dtd_not_standalone);
11956   tcase_add_test__ifdef_xml_dtd(tc_basic, test_invalid_foreign_dtd);
11957   tcase_add_test__ifdef_xml_dtd(tc_basic, test_foreign_dtd_with_doctype);
11958   tcase_add_test__ifdef_xml_dtd(tc_basic,
11959                                 test_foreign_dtd_without_external_subset);
11960   tcase_add_test__ifdef_xml_dtd(tc_basic, test_empty_foreign_dtd);
11961   tcase_add_test(tc_basic, test_set_base);
11962   tcase_add_test(tc_basic, test_attributes);
11963   tcase_add_test(tc_basic, test_reset_in_entity);
11964   tcase_add_test(tc_basic, test_resume_invalid_parse);
11965   tcase_add_test(tc_basic, test_resume_resuspended);
11966   tcase_add_test(tc_basic, test_cdata_default);
11967   tcase_add_test(tc_basic, test_subordinate_reset);
11968   tcase_add_test(tc_basic, test_subordinate_suspend);
11969   tcase_add_test(tc_basic, test_subordinate_xdecl_suspend);
11970   tcase_add_test(tc_basic, test_subordinate_xdecl_abort);
11971   tcase_add_test(tc_basic, test_explicit_encoding);
11972   tcase_add_test(tc_basic, test_trailing_cr);
11973   tcase_add_test(tc_basic, test_ext_entity_trailing_cr);
11974   tcase_add_test(tc_basic, test_trailing_rsqb);
11975   tcase_add_test(tc_basic, test_ext_entity_trailing_rsqb);
11976   tcase_add_test(tc_basic, test_ext_entity_good_cdata);
11977   tcase_add_test__ifdef_xml_dtd(tc_basic, test_user_parameters);
11978   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_ref_parameter);
11979   tcase_add_test(tc_basic, test_empty_parse);
11980   tcase_add_test(tc_basic, test_get_buffer_1);
11981   tcase_add_test(tc_basic, test_get_buffer_2);
11982 #if defined(XML_CONTEXT_BYTES)
11983   tcase_add_test(tc_basic, test_get_buffer_3_overflow);
11984 #endif
11985   tcase_add_test(tc_basic, test_byte_info_at_end);
11986   tcase_add_test(tc_basic, test_byte_info_at_error);
11987   tcase_add_test(tc_basic, test_byte_info_at_cdata);
11988   tcase_add_test(tc_basic, test_predefined_entities);
11989   tcase_add_test__ifdef_xml_dtd(tc_basic, test_invalid_tag_in_dtd);
11990   tcase_add_test(tc_basic, test_not_predefined_entities);
11991   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section);
11992   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section_utf16);
11993   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section_utf16_be);
11994   tcase_add_test__ifdef_xml_dtd(tc_basic, test_bad_ignore_section);
11995   tcase_add_test__ifdef_xml_dtd(tc_basic, test_external_entity_values);
11996   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_not_standalone);
11997   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_value_abort);
11998   tcase_add_test(tc_basic, test_bad_public_doctype);
11999   tcase_add_test(tc_basic, test_attribute_enum_value);
12000   tcase_add_test(tc_basic, test_predefined_entity_redefinition);
12001   tcase_add_test__ifdef_xml_dtd(tc_basic, test_dtd_stop_processing);
12002   tcase_add_test(tc_basic, test_public_notation_no_sysid);
12003   tcase_add_test(tc_basic, test_nested_groups);
12004   tcase_add_test(tc_basic, test_group_choice);
12005   tcase_add_test(tc_basic, test_standalone_parameter_entity);
12006   tcase_add_test__ifdef_xml_dtd(tc_basic, test_skipped_parameter_entity);
12007   tcase_add_test__ifdef_xml_dtd(tc_basic,
12008                                 test_recursive_external_parameter_entity);
12009   tcase_add_test(tc_basic, test_undefined_ext_entity_in_external_dtd);
12010   tcase_add_test(tc_basic, test_suspend_xdecl);
12011   tcase_add_test(tc_basic, test_abort_epilog);
12012   tcase_add_test(tc_basic, test_abort_epilog_2);
12013   tcase_add_test(tc_basic, test_suspend_epilog);
12014   tcase_add_test(tc_basic, test_suspend_in_sole_empty_tag);
12015   tcase_add_test(tc_basic, test_unfinished_epilog);
12016   tcase_add_test(tc_basic, test_partial_char_in_epilog);
12017   tcase_add_test(tc_basic, test_hash_collision);
12018   tcase_add_test__ifdef_xml_dtd(tc_basic, test_suspend_resume_internal_entity);
12019   tcase_add_test__ifdef_xml_dtd(tc_basic, test_resume_entity_with_syntax_error);
12020   tcase_add_test__ifdef_xml_dtd(tc_basic, test_suspend_resume_parameter_entity);
12021   tcase_add_test(tc_basic, test_restart_on_error);
12022   tcase_add_test(tc_basic, test_reject_lt_in_attribute_value);
12023   tcase_add_test(tc_basic, test_reject_unfinished_param_in_att_value);
12024   tcase_add_test(tc_basic, test_trailing_cr_in_att_value);
12025   tcase_add_test(tc_basic, test_standalone_internal_entity);
12026   tcase_add_test(tc_basic, test_skipped_external_entity);
12027   tcase_add_test(tc_basic, test_skipped_null_loaded_ext_entity);
12028   tcase_add_test(tc_basic, test_skipped_unloaded_ext_entity);
12029   tcase_add_test__ifdef_xml_dtd(tc_basic, test_param_entity_with_trailing_cr);
12030   tcase_add_test(tc_basic, test_invalid_character_entity);
12031   tcase_add_test(tc_basic, test_invalid_character_entity_2);
12032   tcase_add_test(tc_basic, test_invalid_character_entity_3);
12033   tcase_add_test(tc_basic, test_invalid_character_entity_4);
12034   tcase_add_test(tc_basic, test_pi_handled_in_default);
12035   tcase_add_test(tc_basic, test_comment_handled_in_default);
12036   tcase_add_test(tc_basic, test_pi_yml);
12037   tcase_add_test(tc_basic, test_pi_xnl);
12038   tcase_add_test(tc_basic, test_pi_xmm);
12039   tcase_add_test(tc_basic, test_utf16_pi);
12040   tcase_add_test(tc_basic, test_utf16_be_pi);
12041   tcase_add_test(tc_basic, test_utf16_be_comment);
12042   tcase_add_test(tc_basic, test_utf16_le_comment);
12043   tcase_add_test(tc_basic, test_missing_encoding_conversion_fn);
12044   tcase_add_test(tc_basic, test_failing_encoding_conversion_fn);
12045   tcase_add_test(tc_basic, test_unknown_encoding_success);
12046   tcase_add_test(tc_basic, test_unknown_encoding_bad_name);
12047   tcase_add_test(tc_basic, test_unknown_encoding_bad_name_2);
12048   tcase_add_test(tc_basic, test_unknown_encoding_long_name_1);
12049   tcase_add_test(tc_basic, test_unknown_encoding_long_name_2);
12050   tcase_add_test(tc_basic, test_invalid_unknown_encoding);
12051   tcase_add_test(tc_basic, test_unknown_ascii_encoding_ok);
12052   tcase_add_test(tc_basic, test_unknown_ascii_encoding_fail);
12053   tcase_add_test(tc_basic, test_unknown_encoding_invalid_length);
12054   tcase_add_test(tc_basic, test_unknown_encoding_invalid_topbit);
12055   tcase_add_test(tc_basic, test_unknown_encoding_invalid_surrogate);
12056   tcase_add_test(tc_basic, test_unknown_encoding_invalid_high);
12057   tcase_add_test(tc_basic, test_unknown_encoding_invalid_attr_value);
12058   tcase_add_test(tc_basic, test_ext_entity_latin1_utf16le_bom);
12059   tcase_add_test(tc_basic, test_ext_entity_latin1_utf16be_bom);
12060   tcase_add_test(tc_basic, test_ext_entity_latin1_utf16le_bom2);
12061   tcase_add_test(tc_basic, test_ext_entity_latin1_utf16be_bom2);
12062   tcase_add_test(tc_basic, test_ext_entity_utf16_be);
12063   tcase_add_test(tc_basic, test_ext_entity_utf16_le);
12064   tcase_add_test(tc_basic, test_ext_entity_utf16_unknown);
12065   tcase_add_test(tc_basic, test_ext_entity_utf8_non_bom);
12066   tcase_add_test(tc_basic, test_utf8_in_cdata_section);
12067   tcase_add_test(tc_basic, test_utf8_in_cdata_section_2);
12068   tcase_add_test(tc_basic, test_utf8_in_start_tags);
12069   tcase_add_test(tc_basic, test_trailing_spaces_in_elements);
12070   tcase_add_test(tc_basic, test_utf16_attribute);
12071   tcase_add_test(tc_basic, test_utf16_second_attr);
12072   tcase_add_test(tc_basic, test_attr_after_solidus);
12073   tcase_add_test__ifdef_xml_dtd(tc_basic, test_utf16_pe);
12074   tcase_add_test(tc_basic, test_bad_attr_desc_keyword);
12075   tcase_add_test(tc_basic, test_bad_attr_desc_keyword_utf16);
12076   tcase_add_test(tc_basic, test_bad_doctype);
12077   tcase_add_test(tc_basic, test_bad_doctype_utf8);
12078   tcase_add_test(tc_basic, test_bad_doctype_utf16);
12079   tcase_add_test(tc_basic, test_bad_doctype_plus);
12080   tcase_add_test(tc_basic, test_bad_doctype_star);
12081   tcase_add_test(tc_basic, test_bad_doctype_query);
12082   tcase_add_test__ifdef_xml_dtd(tc_basic, test_unknown_encoding_bad_ignore);
12083   tcase_add_test(tc_basic, test_entity_in_utf16_be_attr);
12084   tcase_add_test(tc_basic, test_entity_in_utf16_le_attr);
12085   tcase_add_test__ifdef_xml_dtd(tc_basic, test_entity_public_utf16_be);
12086   tcase_add_test__ifdef_xml_dtd(tc_basic, test_entity_public_utf16_le);
12087   tcase_add_test(tc_basic, test_short_doctype);
12088   tcase_add_test(tc_basic, test_short_doctype_2);
12089   tcase_add_test(tc_basic, test_short_doctype_3);
12090   tcase_add_test(tc_basic, test_long_doctype);
12091   tcase_add_test(tc_basic, test_bad_entity);
12092   tcase_add_test(tc_basic, test_bad_entity_2);
12093   tcase_add_test(tc_basic, test_bad_entity_3);
12094   tcase_add_test(tc_basic, test_bad_entity_4);
12095   tcase_add_test(tc_basic, test_bad_notation);
12096   tcase_add_test(tc_basic, test_default_doctype_handler);
12097   tcase_add_test(tc_basic, test_empty_element_abort);
12098 
12099   suite_add_tcase(s, tc_namespace);
12100   tcase_add_checked_fixture(tc_namespace, namespace_setup, namespace_teardown);
12101   tcase_add_test(tc_namespace, test_return_ns_triplet);
12102   tcase_add_test(tc_namespace, test_ns_tagname_overwrite);
12103   tcase_add_test(tc_namespace, test_ns_tagname_overwrite_triplet);
12104   tcase_add_test(tc_namespace, test_start_ns_clears_start_element);
12105   tcase_add_test__ifdef_xml_dtd(tc_namespace,
12106                                 test_default_ns_from_ext_subset_and_ext_ge);
12107   tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_1);
12108   tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_2);
12109   tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_3);
12110   tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_4);
12111   tcase_add_test(tc_namespace, test_ns_unbound_prefix);
12112   tcase_add_test(tc_namespace, test_ns_default_with_empty_uri);
12113   tcase_add_test(tc_namespace, test_ns_duplicate_attrs_diff_prefixes);
12114   tcase_add_test(tc_namespace, test_ns_duplicate_hashes);
12115   tcase_add_test(tc_namespace, test_ns_unbound_prefix_on_attribute);
12116   tcase_add_test(tc_namespace, test_ns_unbound_prefix_on_element);
12117   tcase_add_test(tc_namespace, test_ns_parser_reset);
12118   tcase_add_test(tc_namespace, test_ns_long_element);
12119   tcase_add_test(tc_namespace, test_ns_mixed_prefix_atts);
12120   tcase_add_test(tc_namespace, test_ns_extend_uri_buffer);
12121   tcase_add_test(tc_namespace, test_ns_reserved_attributes);
12122   tcase_add_test(tc_namespace, test_ns_reserved_attributes_2);
12123   tcase_add_test(tc_namespace, test_ns_extremely_long_prefix);
12124   tcase_add_test(tc_namespace, test_ns_unknown_encoding_success);
12125   tcase_add_test(tc_namespace, test_ns_double_colon);
12126   tcase_add_test(tc_namespace, test_ns_double_colon_element);
12127   tcase_add_test(tc_namespace, test_ns_bad_attr_leafname);
12128   tcase_add_test(tc_namespace, test_ns_bad_element_leafname);
12129   tcase_add_test(tc_namespace, test_ns_utf16_leafname);
12130   tcase_add_test(tc_namespace, test_ns_utf16_element_leafname);
12131   tcase_add_test(tc_namespace, test_ns_utf16_doctype);
12132   tcase_add_test(tc_namespace, test_ns_invalid_doctype);
12133   tcase_add_test(tc_namespace, test_ns_double_colon_doctype);
12134   tcase_add_test(tc_namespace, test_ns_separator_in_uri);
12135 
12136   suite_add_tcase(s, tc_misc);
12137   tcase_add_checked_fixture(tc_misc, NULL, basic_teardown);
12138   tcase_add_test(tc_misc, test_misc_alloc_create_parser);
12139   tcase_add_test(tc_misc, test_misc_alloc_create_parser_with_encoding);
12140   tcase_add_test(tc_misc, test_misc_null_parser);
12141   tcase_add_test(tc_misc, test_misc_error_string);
12142   tcase_add_test(tc_misc, test_misc_version);
12143   tcase_add_test(tc_misc, test_misc_features);
12144   tcase_add_test(tc_misc, test_misc_attribute_leak);
12145   tcase_add_test(tc_misc, test_misc_utf16le);
12146   tcase_add_test(tc_misc, test_misc_stop_during_end_handler_issue_240_1);
12147   tcase_add_test(tc_misc, test_misc_stop_during_end_handler_issue_240_2);
12148   tcase_add_test__ifdef_xml_dtd(
12149       tc_misc, test_misc_deny_internal_entity_closing_doctype_issue_317);
12150 
12151   suite_add_tcase(s, tc_alloc);
12152   tcase_add_checked_fixture(tc_alloc, alloc_setup, alloc_teardown);
12153   tcase_add_test(tc_alloc, test_alloc_parse_xdecl);
12154   tcase_add_test(tc_alloc, test_alloc_parse_xdecl_2);
12155   tcase_add_test(tc_alloc, test_alloc_parse_pi);
12156   tcase_add_test(tc_alloc, test_alloc_parse_pi_2);
12157   tcase_add_test(tc_alloc, test_alloc_parse_pi_3);
12158   tcase_add_test(tc_alloc, test_alloc_parse_comment);
12159   tcase_add_test(tc_alloc, test_alloc_parse_comment_2);
12160   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_create_external_parser);
12161   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_run_external_parser);
12162   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_dtd_copy_default_atts);
12163   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_external_entity);
12164   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_ext_entity_set_encoding);
12165   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_internal_entity);
12166   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_dtd_default_handling);
12167   tcase_add_test(tc_alloc, test_alloc_explicit_encoding);
12168   tcase_add_test(tc_alloc, test_alloc_set_base);
12169   tcase_add_test(tc_alloc, test_alloc_realloc_buffer);
12170   tcase_add_test(tc_alloc, test_alloc_ext_entity_realloc_buffer);
12171   tcase_add_test(tc_alloc, test_alloc_realloc_many_attributes);
12172   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_public_entity_value);
12173   tcase_add_test__ifdef_xml_dtd(tc_alloc,
12174                                 test_alloc_realloc_subst_public_entity_value);
12175   tcase_add_test(tc_alloc, test_alloc_parse_public_doctype);
12176   tcase_add_test(tc_alloc, test_alloc_parse_public_doctype_long_name);
12177   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_set_foreign_dtd);
12178   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_attribute_enum_value);
12179   tcase_add_test__ifdef_xml_dtd(tc_alloc,
12180                                 test_alloc_realloc_attribute_enum_value);
12181   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_implied_attribute);
12182   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_default_attribute);
12183   tcase_add_test(tc_alloc, test_alloc_notation);
12184   tcase_add_test(tc_alloc, test_alloc_public_notation);
12185   tcase_add_test(tc_alloc, test_alloc_system_notation);
12186   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_nested_groups);
12187   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_nested_groups);
12188   tcase_add_test(tc_alloc, test_alloc_large_group);
12189   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_group_choice);
12190   tcase_add_test(tc_alloc, test_alloc_pi_in_epilog);
12191   tcase_add_test(tc_alloc, test_alloc_comment_in_epilog);
12192   tcase_add_test__ifdef_xml_dtd(tc_alloc,
12193                                 test_alloc_realloc_long_attribute_value);
12194   tcase_add_test(tc_alloc, test_alloc_attribute_whitespace);
12195   tcase_add_test(tc_alloc, test_alloc_attribute_predefined_entity);
12196   tcase_add_test(tc_alloc, test_alloc_long_attr_default_with_char_ref);
12197   tcase_add_test(tc_alloc, test_alloc_long_attr_value);
12198   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_nested_entities);
12199   tcase_add_test__ifdef_xml_dtd(tc_alloc,
12200                                 test_alloc_realloc_param_entity_newline);
12201   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_ce_extends_pe);
12202   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_attributes);
12203   tcase_add_test(tc_alloc, test_alloc_long_doc_name);
12204   tcase_add_test(tc_alloc, test_alloc_long_base);
12205   tcase_add_test(tc_alloc, test_alloc_long_public_id);
12206   tcase_add_test(tc_alloc, test_alloc_long_entity_value);
12207   tcase_add_test(tc_alloc, test_alloc_long_notation);
12208 
12209   suite_add_tcase(s, tc_nsalloc);
12210   tcase_add_checked_fixture(tc_nsalloc, nsalloc_setup, nsalloc_teardown);
12211   tcase_add_test(tc_nsalloc, test_nsalloc_xmlns);
12212   tcase_add_test(tc_nsalloc, test_nsalloc_parse_buffer);
12213   tcase_add_test(tc_nsalloc, test_nsalloc_long_prefix);
12214   tcase_add_test(tc_nsalloc, test_nsalloc_long_uri);
12215   tcase_add_test(tc_nsalloc, test_nsalloc_long_attr);
12216   tcase_add_test(tc_nsalloc, test_nsalloc_long_attr_prefix);
12217   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_attributes);
12218   tcase_add_test(tc_nsalloc, test_nsalloc_long_element);
12219   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_binding_uri);
12220   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_prefix);
12221   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_longer_prefix);
12222   tcase_add_test(tc_nsalloc, test_nsalloc_long_namespace);
12223   tcase_add_test(tc_nsalloc, test_nsalloc_less_long_namespace);
12224   tcase_add_test(tc_nsalloc, test_nsalloc_long_context);
12225   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context);
12226   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_2);
12227   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_3);
12228   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_4);
12229   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_5);
12230   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_6);
12231   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_7);
12232   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_ge_name);
12233   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_in_dtd);
12234   tcase_add_test(tc_nsalloc, test_nsalloc_long_default_in_ext);
12235   tcase_add_test(tc_nsalloc, test_nsalloc_long_systemid_in_ext);
12236   tcase_add_test(tc_nsalloc, test_nsalloc_prefixed_element);
12237 
12238 #if defined(XML_DTD)
12239   suite_add_tcase(s, tc_accounting);
12240   tcase_add_test(tc_accounting, test_accounting_precision);
12241   tcase_add_test(tc_accounting, test_billion_laughs_attack_protection_api);
12242   tcase_add_test(tc_accounting, test_helper_unsigned_char_to_printable);
12243 #endif
12244 
12245   return s;
12246 }
12247 
12248 int
main(int argc,char * argv[])12249 main(int argc, char *argv[]) {
12250   int i, nf;
12251   int verbosity = CK_NORMAL;
12252   Suite *s = make_suite();
12253   SRunner *sr = srunner_create(s);
12254 
12255   /* run the tests for internal helper functions */
12256   testhelper_is_whitespace_normalized();
12257 
12258   for (i = 1; i < argc; ++i) {
12259     char *opt = argv[i];
12260     if (strcmp(opt, "-v") == 0 || strcmp(opt, "--verbose") == 0)
12261       verbosity = CK_VERBOSE;
12262     else if (strcmp(opt, "-q") == 0 || strcmp(opt, "--quiet") == 0)
12263       verbosity = CK_SILENT;
12264     else {
12265       fprintf(stderr, "runtests: unknown option '%s'\n", opt);
12266       return 2;
12267     }
12268   }
12269   if (verbosity != CK_SILENT)
12270     printf("Expat version: %" XML_FMT_STR "\n", XML_ExpatVersion());
12271   srunner_run_all(sr, verbosity);
12272   nf = srunner_ntests_failed(sr);
12273   srunner_free(sr);
12274 
12275   return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
12276 }
12277