• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <ssolie@users.sourceforge.net>
12    Copyright (c) 2005-2012 Karl Waclawek <karl@waclawek.net>
13    Copyright (c) 2016-2021 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    Licensed under the MIT license:
21 
22    Permission is  hereby granted,  free of charge,  to any  person obtaining
23    a  copy  of  this  software   and  associated  documentation  files  (the
24    "Software"),  to  deal in  the  Software  without restriction,  including
25    without  limitation the  rights  to use,  copy,  modify, merge,  publish,
26    distribute, sublicense, and/or sell copies of the Software, and to permit
27    persons  to whom  the Software  is  furnished to  do so,  subject to  the
28    following conditions:
29 
30    The above copyright  notice and this permission notice  shall be included
31    in all copies or substantial portions of the Software.
32 
33    THE  SOFTWARE  IS  PROVIDED  "AS  IS",  WITHOUT  WARRANTY  OF  ANY  KIND,
34    EXPRESS  OR IMPLIED,  INCLUDING  BUT  NOT LIMITED  TO  THE WARRANTIES  OF
35    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
36    NO EVENT SHALL THE AUTHORS OR  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
37    DAMAGES OR  OTHER LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT,  TORT OR
38    OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
39    USE OR OTHER DEALINGS IN THE SOFTWARE.
40 */
41 
42 #if defined(NDEBUG)
43 #  undef NDEBUG /* because test suite relies on assert(...) at the moment */
44 #endif
45 
46 #include <expat_config.h>
47 
48 #include <assert.h>
49 #include <stdlib.h>
50 #include <stdio.h>
51 #include <string.h>
52 #include <stddef.h> /* ptrdiff_t */
53 #include <ctype.h>
54 #include <limits.h>
55 #include <stdint.h> /* intptr_t uint64_t */
56 #include <math.h>   /* NAN, INFINITY, isnan */
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 /* Test foreign DTD handling */
START_TEST(test_set_foreign_dtd)2667 START_TEST(test_set_foreign_dtd) {
2668   const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n";
2669   const char *text2 = "<doc>&entity;</doc>";
2670   ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
2671 
2672   /* Check hash salt is passed through too */
2673   XML_SetHashSalt(g_parser, 0x12345678);
2674   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2675   XML_SetUserData(g_parser, &test_data);
2676   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
2677   /* Add a default handler to exercise more code paths */
2678   XML_SetDefaultHandler(g_parser, dummy_default_handler);
2679   if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE)
2680     fail("Could not set foreign DTD");
2681   if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
2682       == XML_STATUS_ERROR)
2683     xml_failure(g_parser);
2684 
2685   /* Ensure that trying to set the DTD after parsing has started
2686    * is faulted, even if it's the same setting.
2687    */
2688   if (XML_UseForeignDTD(g_parser, XML_TRUE)
2689       != XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING)
2690     fail("Failed to reject late foreign DTD setting");
2691   /* Ditto for the hash salt */
2692   if (XML_SetHashSalt(g_parser, 0x23456789))
2693     fail("Failed to reject late hash salt change");
2694 
2695   /* Now finish the parse */
2696   if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
2697       == XML_STATUS_ERROR)
2698     xml_failure(g_parser);
2699 }
2700 END_TEST
2701 
2702 /* Test foreign DTD handling with a failing NotStandalone handler */
START_TEST(test_foreign_dtd_not_standalone)2703 START_TEST(test_foreign_dtd_not_standalone) {
2704   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
2705                      "<doc>&entity;</doc>";
2706   ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
2707 
2708   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2709   XML_SetUserData(g_parser, &test_data);
2710   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
2711   XML_SetNotStandaloneHandler(g_parser, reject_not_standalone_handler);
2712   if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE)
2713     fail("Could not set foreign DTD");
2714   expect_failure(text, XML_ERROR_NOT_STANDALONE,
2715                  "NotStandalonehandler failed to reject");
2716 }
2717 END_TEST
2718 
2719 /* Test invalid character in a foreign DTD is faulted */
START_TEST(test_invalid_foreign_dtd)2720 START_TEST(test_invalid_foreign_dtd) {
2721   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
2722                      "<doc>&entity;</doc>";
2723   ExtFaults test_data
2724       = {"$", "Dollar not faulted", NULL, XML_ERROR_INVALID_TOKEN};
2725 
2726   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2727   XML_SetUserData(g_parser, &test_data);
2728   XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
2729   XML_UseForeignDTD(g_parser, XML_TRUE);
2730   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
2731                  "Bad DTD should not have been accepted");
2732 }
2733 END_TEST
2734 
2735 /* Test foreign DTD use with a doctype */
START_TEST(test_foreign_dtd_with_doctype)2736 START_TEST(test_foreign_dtd_with_doctype) {
2737   const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n"
2738                       "<!DOCTYPE doc [<!ENTITY entity 'hello world'>]>\n";
2739   const char *text2 = "<doc>&entity;</doc>";
2740   ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
2741 
2742   /* Check hash salt is passed through too */
2743   XML_SetHashSalt(g_parser, 0x12345678);
2744   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2745   XML_SetUserData(g_parser, &test_data);
2746   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
2747   /* Add a default handler to exercise more code paths */
2748   XML_SetDefaultHandler(g_parser, dummy_default_handler);
2749   if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE)
2750     fail("Could not set foreign DTD");
2751   if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
2752       == XML_STATUS_ERROR)
2753     xml_failure(g_parser);
2754 
2755   /* Ensure that trying to set the DTD after parsing has started
2756    * is faulted, even if it's the same setting.
2757    */
2758   if (XML_UseForeignDTD(g_parser, XML_TRUE)
2759       != XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING)
2760     fail("Failed to reject late foreign DTD setting");
2761   /* Ditto for the hash salt */
2762   if (XML_SetHashSalt(g_parser, 0x23456789))
2763     fail("Failed to reject late hash salt change");
2764 
2765   /* Now finish the parse */
2766   if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
2767       == XML_STATUS_ERROR)
2768     xml_failure(g_parser);
2769 }
2770 END_TEST
2771 
2772 /* Test XML_UseForeignDTD with no external subset present */
2773 static int XMLCALL
external_entity_null_loader(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)2774 external_entity_null_loader(XML_Parser parser, const XML_Char *context,
2775                             const XML_Char *base, const XML_Char *systemId,
2776                             const XML_Char *publicId) {
2777   UNUSED_P(parser);
2778   UNUSED_P(context);
2779   UNUSED_P(base);
2780   UNUSED_P(systemId);
2781   UNUSED_P(publicId);
2782   return XML_STATUS_OK;
2783 }
2784 
START_TEST(test_foreign_dtd_without_external_subset)2785 START_TEST(test_foreign_dtd_without_external_subset) {
2786   const char *text = "<!DOCTYPE doc [<!ENTITY foo 'bar'>]>\n"
2787                      "<doc>&foo;</doc>";
2788 
2789   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2790   XML_SetUserData(g_parser, NULL);
2791   XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader);
2792   XML_UseForeignDTD(g_parser, XML_TRUE);
2793   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2794       == XML_STATUS_ERROR)
2795     xml_failure(g_parser);
2796 }
2797 END_TEST
2798 
START_TEST(test_empty_foreign_dtd)2799 START_TEST(test_empty_foreign_dtd) {
2800   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
2801                      "<doc>&entity;</doc>";
2802 
2803   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2804   XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader);
2805   XML_UseForeignDTD(g_parser, XML_TRUE);
2806   expect_failure(text, XML_ERROR_UNDEFINED_ENTITY,
2807                  "Undefined entity not faulted");
2808 }
2809 END_TEST
2810 
2811 /* Test XML Base is set and unset appropriately */
START_TEST(test_set_base)2812 START_TEST(test_set_base) {
2813   const XML_Char *old_base;
2814   const XML_Char *new_base = XCS("/local/file/name.xml");
2815 
2816   old_base = XML_GetBase(g_parser);
2817   if (XML_SetBase(g_parser, new_base) != XML_STATUS_OK)
2818     fail("Unable to set base");
2819   if (xcstrcmp(XML_GetBase(g_parser), new_base) != 0)
2820     fail("Base setting not correct");
2821   if (XML_SetBase(g_parser, NULL) != XML_STATUS_OK)
2822     fail("Unable to NULL base");
2823   if (XML_GetBase(g_parser) != NULL)
2824     fail("Base setting not nulled");
2825   XML_SetBase(g_parser, old_base);
2826 }
2827 END_TEST
2828 
2829 /* Test attribute counts, indexing, etc */
2830 typedef struct attrInfo {
2831   const XML_Char *name;
2832   const XML_Char *value;
2833 } AttrInfo;
2834 
2835 typedef struct elementInfo {
2836   const XML_Char *name;
2837   int attr_count;
2838   const XML_Char *id_name;
2839   AttrInfo *attributes;
2840 } ElementInfo;
2841 
2842 static void XMLCALL
counting_start_element_handler(void * userData,const XML_Char * name,const XML_Char ** atts)2843 counting_start_element_handler(void *userData, const XML_Char *name,
2844                                const XML_Char **atts) {
2845   ElementInfo *info = (ElementInfo *)userData;
2846   AttrInfo *attr;
2847   int count, id, i;
2848 
2849   while (info->name != NULL) {
2850     if (! xcstrcmp(name, info->name))
2851       break;
2852     info++;
2853   }
2854   if (info->name == NULL)
2855     fail("Element not recognised");
2856   /* The attribute count is twice what you might expect.  It is a
2857    * count of items in atts, an array which contains alternating
2858    * attribute names and attribute values.  For the naive user this
2859    * is possibly a little unexpected, but it is what the
2860    * documentation in expat.h tells us to expect.
2861    */
2862   count = XML_GetSpecifiedAttributeCount(g_parser);
2863   if (info->attr_count * 2 != count) {
2864     fail("Not got expected attribute count");
2865     return;
2866   }
2867   id = XML_GetIdAttributeIndex(g_parser);
2868   if (id == -1 && info->id_name != NULL) {
2869     fail("ID not present");
2870     return;
2871   }
2872   if (id != -1 && xcstrcmp(atts[id], info->id_name)) {
2873     fail("ID does not have the correct name");
2874     return;
2875   }
2876   for (i = 0; i < info->attr_count; i++) {
2877     attr = info->attributes;
2878     while (attr->name != NULL) {
2879       if (! xcstrcmp(atts[0], attr->name))
2880         break;
2881       attr++;
2882     }
2883     if (attr->name == NULL) {
2884       fail("Attribute not recognised");
2885       return;
2886     }
2887     if (xcstrcmp(atts[1], attr->value)) {
2888       fail("Attribute has wrong value");
2889       return;
2890     }
2891     /* Remember, two entries in atts per attribute (see above) */
2892     atts += 2;
2893   }
2894 }
2895 
START_TEST(test_attributes)2896 START_TEST(test_attributes) {
2897   const char *text = "<!DOCTYPE doc [\n"
2898                      "<!ELEMENT doc (tag)>\n"
2899                      "<!ATTLIST doc id ID #REQUIRED>\n"
2900                      "]>"
2901                      "<doc a='1' id='one' b='2'>"
2902                      "<tag c='3'/>"
2903                      "</doc>";
2904   AttrInfo doc_info[] = {{XCS("a"), XCS("1")},
2905                          {XCS("b"), XCS("2")},
2906                          {XCS("id"), XCS("one")},
2907                          {NULL, NULL}};
2908   AttrInfo tag_info[] = {{XCS("c"), XCS("3")}, {NULL, NULL}};
2909   ElementInfo info[] = {{XCS("doc"), 3, XCS("id"), NULL},
2910                         {XCS("tag"), 1, NULL, NULL},
2911                         {NULL, 0, NULL, NULL}};
2912   info[0].attributes = doc_info;
2913   info[1].attributes = tag_info;
2914 
2915   XML_SetStartElementHandler(g_parser, counting_start_element_handler);
2916   XML_SetUserData(g_parser, info);
2917   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2918       == XML_STATUS_ERROR)
2919     xml_failure(g_parser);
2920 }
2921 END_TEST
2922 
2923 /* Test reset works correctly in the middle of processing an internal
2924  * entity.  Exercises some obscure code in XML_ParserReset().
2925  */
START_TEST(test_reset_in_entity)2926 START_TEST(test_reset_in_entity) {
2927   const char *text = "<!DOCTYPE doc [\n"
2928                      "<!ENTITY wombat 'wom'>\n"
2929                      "<!ENTITY entity 'hi &wom; there'>\n"
2930                      "]>\n"
2931                      "<doc>&entity;</doc>";
2932   XML_ParsingStatus status;
2933 
2934   resumable = XML_TRUE;
2935   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2936   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
2937       == XML_STATUS_ERROR)
2938     xml_failure(g_parser);
2939   XML_GetParsingStatus(g_parser, &status);
2940   if (status.parsing != XML_SUSPENDED)
2941     fail("Parsing status not SUSPENDED");
2942   XML_ParserReset(g_parser, NULL);
2943   XML_GetParsingStatus(g_parser, &status);
2944   if (status.parsing != XML_INITIALIZED)
2945     fail("Parsing status doesn't reset to INITIALIZED");
2946 }
2947 END_TEST
2948 
2949 /* Test that resume correctly passes through parse errors */
START_TEST(test_resume_invalid_parse)2950 START_TEST(test_resume_invalid_parse) {
2951   const char *text = "<doc>Hello</doc"; /* Missing closing wedge */
2952 
2953   resumable = XML_TRUE;
2954   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2955   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
2956       == XML_STATUS_ERROR)
2957     xml_failure(g_parser);
2958   if (XML_ResumeParser(g_parser) == XML_STATUS_OK)
2959     fail("Resumed invalid parse not faulted");
2960   if (XML_GetErrorCode(g_parser) != XML_ERROR_UNCLOSED_TOKEN)
2961     fail("Invalid parse not correctly faulted");
2962 }
2963 END_TEST
2964 
2965 /* Test that re-suspended parses are correctly passed through */
START_TEST(test_resume_resuspended)2966 START_TEST(test_resume_resuspended) {
2967   const char *text = "<doc>Hello<meep/>world</doc>";
2968 
2969   resumable = XML_TRUE;
2970   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2971   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
2972       == XML_STATUS_ERROR)
2973     xml_failure(g_parser);
2974   resumable = XML_TRUE;
2975   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2976   if (XML_ResumeParser(g_parser) != XML_STATUS_SUSPENDED)
2977     fail("Resumption not suspended");
2978   /* This one should succeed and finish up */
2979   if (XML_ResumeParser(g_parser) != XML_STATUS_OK)
2980     xml_failure(g_parser);
2981 }
2982 END_TEST
2983 
2984 /* Test that CDATA shows up correctly through a default handler */
START_TEST(test_cdata_default)2985 START_TEST(test_cdata_default) {
2986   const char *text = "<doc><![CDATA[Hello\nworld]]></doc>";
2987   const XML_Char *expected = XCS("<doc><![CDATA[Hello\nworld]]></doc>");
2988   CharData storage;
2989 
2990   CharData_Init(&storage);
2991   XML_SetUserData(g_parser, &storage);
2992   XML_SetDefaultHandler(g_parser, accumulate_characters);
2993 
2994   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2995       == XML_STATUS_ERROR)
2996     xml_failure(g_parser);
2997   CharData_CheckXMLChars(&storage, expected);
2998 }
2999 END_TEST
3000 
3001 /* Test resetting a subordinate parser does exactly nothing */
3002 static int XMLCALL
external_entity_resetter(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3003 external_entity_resetter(XML_Parser parser, const XML_Char *context,
3004                          const XML_Char *base, const XML_Char *systemId,
3005                          const XML_Char *publicId) {
3006   const char *text = "<!ELEMENT doc (#PCDATA)*>";
3007   XML_Parser ext_parser;
3008   XML_ParsingStatus status;
3009 
3010   UNUSED_P(base);
3011   UNUSED_P(systemId);
3012   UNUSED_P(publicId);
3013   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3014   if (ext_parser == NULL)
3015     fail("Could not create external entity parser");
3016   XML_GetParsingStatus(ext_parser, &status);
3017   if (status.parsing != XML_INITIALIZED) {
3018     fail("Parsing status is not INITIALIZED");
3019     return XML_STATUS_ERROR;
3020   }
3021   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3022       == XML_STATUS_ERROR) {
3023     xml_failure(parser);
3024     return XML_STATUS_ERROR;
3025   }
3026   XML_GetParsingStatus(ext_parser, &status);
3027   if (status.parsing != XML_FINISHED) {
3028     fail("Parsing status is not FINISHED");
3029     return XML_STATUS_ERROR;
3030   }
3031   /* Check we can't parse here */
3032   if (XML_Parse(ext_parser, text, (int)strlen(text), XML_TRUE)
3033       != XML_STATUS_ERROR)
3034     fail("Parsing when finished not faulted");
3035   if (XML_GetErrorCode(ext_parser) != XML_ERROR_FINISHED)
3036     fail("Parsing when finished faulted with wrong code");
3037   XML_ParserReset(ext_parser, NULL);
3038   XML_GetParsingStatus(ext_parser, &status);
3039   if (status.parsing != XML_FINISHED) {
3040     fail("Parsing status not still FINISHED");
3041     return XML_STATUS_ERROR;
3042   }
3043   XML_ParserFree(ext_parser);
3044   return XML_STATUS_OK;
3045 }
3046 
START_TEST(test_subordinate_reset)3047 START_TEST(test_subordinate_reset) {
3048   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
3049                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
3050                      "<doc>&entity;</doc>";
3051 
3052   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3053   XML_SetExternalEntityRefHandler(g_parser, external_entity_resetter);
3054   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3055       == XML_STATUS_ERROR)
3056     xml_failure(g_parser);
3057 }
3058 END_TEST
3059 
3060 /* Test suspending a subordinate parser */
3061 
3062 static void XMLCALL
entity_suspending_decl_handler(void * userData,const XML_Char * name,XML_Content * model)3063 entity_suspending_decl_handler(void *userData, const XML_Char *name,
3064                                XML_Content *model) {
3065   XML_Parser ext_parser = (XML_Parser)userData;
3066 
3067   UNUSED_P(name);
3068   if (XML_StopParser(ext_parser, XML_TRUE) != XML_STATUS_ERROR)
3069     fail("Attempting to suspend a subordinate parser not faulted");
3070   if (XML_GetErrorCode(ext_parser) != XML_ERROR_SUSPEND_PE)
3071     fail("Suspending subordinate parser get wrong code");
3072   XML_SetElementDeclHandler(ext_parser, NULL);
3073   XML_FreeContentModel(g_parser, model);
3074 }
3075 
3076 static int XMLCALL
external_entity_suspender(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3077 external_entity_suspender(XML_Parser parser, const XML_Char *context,
3078                           const XML_Char *base, const XML_Char *systemId,
3079                           const XML_Char *publicId) {
3080   const char *text = "<!ELEMENT doc (#PCDATA)*>";
3081   XML_Parser ext_parser;
3082 
3083   UNUSED_P(base);
3084   UNUSED_P(systemId);
3085   UNUSED_P(publicId);
3086   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3087   if (ext_parser == NULL)
3088     fail("Could not create external entity parser");
3089   XML_SetElementDeclHandler(ext_parser, entity_suspending_decl_handler);
3090   XML_SetUserData(ext_parser, ext_parser);
3091   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3092       == XML_STATUS_ERROR) {
3093     xml_failure(ext_parser);
3094     return XML_STATUS_ERROR;
3095   }
3096   XML_ParserFree(ext_parser);
3097   return XML_STATUS_OK;
3098 }
3099 
START_TEST(test_subordinate_suspend)3100 START_TEST(test_subordinate_suspend) {
3101   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
3102                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
3103                      "<doc>&entity;</doc>";
3104 
3105   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3106   XML_SetExternalEntityRefHandler(g_parser, external_entity_suspender);
3107   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3108       == XML_STATUS_ERROR)
3109     xml_failure(g_parser);
3110 }
3111 END_TEST
3112 
3113 /* Test suspending a subordinate parser from an XML declaration */
3114 /* Increases code coverage of the tests */
3115 static void XMLCALL
entity_suspending_xdecl_handler(void * userData,const XML_Char * version,const XML_Char * encoding,int standalone)3116 entity_suspending_xdecl_handler(void *userData, const XML_Char *version,
3117                                 const XML_Char *encoding, int standalone) {
3118   XML_Parser ext_parser = (XML_Parser)userData;
3119 
3120   UNUSED_P(version);
3121   UNUSED_P(encoding);
3122   UNUSED_P(standalone);
3123   XML_StopParser(ext_parser, resumable);
3124   XML_SetXmlDeclHandler(ext_parser, NULL);
3125 }
3126 
3127 static int XMLCALL
external_entity_suspend_xmldecl(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3128 external_entity_suspend_xmldecl(XML_Parser parser, const XML_Char *context,
3129                                 const XML_Char *base, const XML_Char *systemId,
3130                                 const XML_Char *publicId) {
3131   const char *text = "<?xml version='1.0' encoding='us-ascii'?>";
3132   XML_Parser ext_parser;
3133   XML_ParsingStatus status;
3134   enum XML_Status rc;
3135 
3136   UNUSED_P(base);
3137   UNUSED_P(systemId);
3138   UNUSED_P(publicId);
3139   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3140   if (ext_parser == NULL)
3141     fail("Could not create external entity parser");
3142   XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
3143   XML_SetUserData(ext_parser, ext_parser);
3144   rc = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
3145   XML_GetParsingStatus(ext_parser, &status);
3146   if (resumable) {
3147     if (rc == XML_STATUS_ERROR)
3148       xml_failure(ext_parser);
3149     if (status.parsing != XML_SUSPENDED)
3150       fail("Ext Parsing status not SUSPENDED");
3151   } else {
3152     if (rc != XML_STATUS_ERROR)
3153       fail("Ext parsing not aborted");
3154     if (XML_GetErrorCode(ext_parser) != XML_ERROR_ABORTED)
3155       xml_failure(ext_parser);
3156     if (status.parsing != XML_FINISHED)
3157       fail("Ext Parsing status not FINISHED");
3158   }
3159 
3160   XML_ParserFree(ext_parser);
3161   return XML_STATUS_OK;
3162 }
3163 
START_TEST(test_subordinate_xdecl_suspend)3164 START_TEST(test_subordinate_xdecl_suspend) {
3165   const char *text
3166       = "<!DOCTYPE doc [\n"
3167         "  <!ENTITY entity SYSTEM 'http://example.org/dummy.ent'>\n"
3168         "]>\n"
3169         "<doc>&entity;</doc>";
3170 
3171   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3172   XML_SetExternalEntityRefHandler(g_parser, external_entity_suspend_xmldecl);
3173   resumable = XML_TRUE;
3174   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3175       == XML_STATUS_ERROR)
3176     xml_failure(g_parser);
3177 }
3178 END_TEST
3179 
START_TEST(test_subordinate_xdecl_abort)3180 START_TEST(test_subordinate_xdecl_abort) {
3181   const char *text
3182       = "<!DOCTYPE doc [\n"
3183         "  <!ENTITY entity SYSTEM 'http://example.org/dummy.ent'>\n"
3184         "]>\n"
3185         "<doc>&entity;</doc>";
3186 
3187   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3188   XML_SetExternalEntityRefHandler(g_parser, external_entity_suspend_xmldecl);
3189   resumable = XML_FALSE;
3190   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3191       == XML_STATUS_ERROR)
3192     xml_failure(g_parser);
3193 }
3194 END_TEST
3195 
3196 /* Test external entity fault handling with suspension */
3197 static int XMLCALL
external_entity_suspending_faulter(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3198 external_entity_suspending_faulter(XML_Parser parser, const XML_Char *context,
3199                                    const XML_Char *base,
3200                                    const XML_Char *systemId,
3201                                    const XML_Char *publicId) {
3202   XML_Parser ext_parser;
3203   ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser);
3204   void *buffer;
3205   int parse_len = (int)strlen(fault->parse_text);
3206 
3207   UNUSED_P(base);
3208   UNUSED_P(systemId);
3209   UNUSED_P(publicId);
3210   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3211   if (ext_parser == NULL)
3212     fail("Could not create external entity parser");
3213   XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
3214   XML_SetUserData(ext_parser, ext_parser);
3215   resumable = XML_TRUE;
3216   buffer = XML_GetBuffer(ext_parser, parse_len);
3217   if (buffer == NULL)
3218     fail("Could not allocate parse buffer");
3219   assert(buffer != NULL);
3220   memcpy(buffer, fault->parse_text, parse_len);
3221   if (XML_ParseBuffer(ext_parser, parse_len, XML_FALSE) != XML_STATUS_SUSPENDED)
3222     fail("XML declaration did not suspend");
3223   if (XML_ResumeParser(ext_parser) != XML_STATUS_OK)
3224     xml_failure(ext_parser);
3225   if (XML_ParseBuffer(ext_parser, 0, XML_TRUE) != XML_STATUS_ERROR)
3226     fail(fault->fail_text);
3227   if (XML_GetErrorCode(ext_parser) != fault->error)
3228     xml_failure(ext_parser);
3229 
3230   XML_ParserFree(ext_parser);
3231   return XML_STATUS_ERROR;
3232 }
3233 
START_TEST(test_ext_entity_invalid_suspended_parse)3234 START_TEST(test_ext_entity_invalid_suspended_parse) {
3235   const char *text = "<!DOCTYPE doc [\n"
3236                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
3237                      "]>\n"
3238                      "<doc>&en;</doc>";
3239   ExtFaults faults[]
3240       = {{"<?xml version='1.0' encoding='us-ascii'?><",
3241           "Incomplete element declaration not faulted", NULL,
3242           XML_ERROR_UNCLOSED_TOKEN},
3243          {/* First two bytes of a three-byte char */
3244           "<?xml version='1.0' encoding='utf-8'?>\xe2\x82",
3245           "Incomplete character not faulted", NULL, XML_ERROR_PARTIAL_CHAR},
3246          {NULL, NULL, NULL, XML_ERROR_NONE}};
3247   ExtFaults *fault;
3248 
3249   for (fault = &faults[0]; fault->parse_text != NULL; fault++) {
3250     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3251     XML_SetExternalEntityRefHandler(g_parser,
3252                                     external_entity_suspending_faulter);
3253     XML_SetUserData(g_parser, fault);
3254     expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
3255                    "Parser did not report external entity error");
3256     XML_ParserReset(g_parser, NULL);
3257   }
3258 }
3259 END_TEST
3260 
3261 /* Test setting an explicit encoding */
START_TEST(test_explicit_encoding)3262 START_TEST(test_explicit_encoding) {
3263   const char *text1 = "<doc>Hello ";
3264   const char *text2 = " World</doc>";
3265 
3266   /* Just check that we can set the encoding to NULL before starting */
3267   if (XML_SetEncoding(g_parser, NULL) != XML_STATUS_OK)
3268     fail("Failed to initialise encoding to NULL");
3269   /* Say we are UTF-8 */
3270   if (XML_SetEncoding(g_parser, XCS("utf-8")) != XML_STATUS_OK)
3271     fail("Failed to set explicit encoding");
3272   if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
3273       == XML_STATUS_ERROR)
3274     xml_failure(g_parser);
3275   /* Try to switch encodings mid-parse */
3276   if (XML_SetEncoding(g_parser, XCS("us-ascii")) != XML_STATUS_ERROR)
3277     fail("Allowed encoding change");
3278   if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
3279       == XML_STATUS_ERROR)
3280     xml_failure(g_parser);
3281   /* Try now the parse is over */
3282   if (XML_SetEncoding(g_parser, NULL) != XML_STATUS_OK)
3283     fail("Failed to unset encoding");
3284 }
3285 END_TEST
3286 
3287 /* Test handling of trailing CR (rather than newline) */
3288 static void XMLCALL
cr_cdata_handler(void * userData,const XML_Char * s,int len)3289 cr_cdata_handler(void *userData, const XML_Char *s, int len) {
3290   int *pfound = (int *)userData;
3291 
3292   /* Internal processing turns the CR into a newline for the
3293    * character data handler, but not for the default handler
3294    */
3295   if (len == 1 && (*s == XCS('\n') || *s == XCS('\r')))
3296     *pfound = 1;
3297 }
3298 
START_TEST(test_trailing_cr)3299 START_TEST(test_trailing_cr) {
3300   const char *text = "<doc>\r";
3301   int found_cr;
3302 
3303   /* Try with a character handler, for code coverage */
3304   XML_SetCharacterDataHandler(g_parser, cr_cdata_handler);
3305   XML_SetUserData(g_parser, &found_cr);
3306   found_cr = 0;
3307   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3308       == XML_STATUS_OK)
3309     fail("Failed to fault unclosed doc");
3310   if (found_cr == 0)
3311     fail("Did not catch the carriage return");
3312   XML_ParserReset(g_parser, NULL);
3313 
3314   /* Now with a default handler instead */
3315   XML_SetDefaultHandler(g_parser, cr_cdata_handler);
3316   XML_SetUserData(g_parser, &found_cr);
3317   found_cr = 0;
3318   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3319       == XML_STATUS_OK)
3320     fail("Failed to fault unclosed doc");
3321   if (found_cr == 0)
3322     fail("Did not catch default carriage return");
3323 }
3324 END_TEST
3325 
3326 /* Test trailing CR in an external entity parse */
3327 static int XMLCALL
external_entity_cr_catcher(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3328 external_entity_cr_catcher(XML_Parser parser, const XML_Char *context,
3329                            const XML_Char *base, const XML_Char *systemId,
3330                            const XML_Char *publicId) {
3331   const char *text = "\r";
3332   XML_Parser ext_parser;
3333 
3334   UNUSED_P(base);
3335   UNUSED_P(systemId);
3336   UNUSED_P(publicId);
3337   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3338   if (ext_parser == NULL)
3339     fail("Could not create external entity parser");
3340   XML_SetCharacterDataHandler(ext_parser, cr_cdata_handler);
3341   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3342       == XML_STATUS_ERROR)
3343     xml_failure(ext_parser);
3344   XML_ParserFree(ext_parser);
3345   return XML_STATUS_OK;
3346 }
3347 
3348 static int XMLCALL
external_entity_bad_cr_catcher(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3349 external_entity_bad_cr_catcher(XML_Parser parser, const XML_Char *context,
3350                                const XML_Char *base, const XML_Char *systemId,
3351                                const XML_Char *publicId) {
3352   const char *text = "<tag>\r";
3353   XML_Parser ext_parser;
3354 
3355   UNUSED_P(base);
3356   UNUSED_P(systemId);
3357   UNUSED_P(publicId);
3358   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3359   if (ext_parser == NULL)
3360     fail("Could not create external entity parser");
3361   XML_SetCharacterDataHandler(ext_parser, cr_cdata_handler);
3362   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3363       == XML_STATUS_OK)
3364     fail("Async entity error not caught");
3365   if (XML_GetErrorCode(ext_parser) != XML_ERROR_ASYNC_ENTITY)
3366     xml_failure(ext_parser);
3367   XML_ParserFree(ext_parser);
3368   return XML_STATUS_OK;
3369 }
3370 
START_TEST(test_ext_entity_trailing_cr)3371 START_TEST(test_ext_entity_trailing_cr) {
3372   const char *text = "<!DOCTYPE doc [\n"
3373                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
3374                      "]>\n"
3375                      "<doc>&en;</doc>";
3376   int found_cr;
3377 
3378   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3379   XML_SetExternalEntityRefHandler(g_parser, external_entity_cr_catcher);
3380   XML_SetUserData(g_parser, &found_cr);
3381   found_cr = 0;
3382   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3383       != XML_STATUS_OK)
3384     xml_failure(g_parser);
3385   if (found_cr == 0)
3386     fail("No carriage return found");
3387   XML_ParserReset(g_parser, NULL);
3388 
3389   /* Try again with a different trailing CR */
3390   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3391   XML_SetExternalEntityRefHandler(g_parser, external_entity_bad_cr_catcher);
3392   XML_SetUserData(g_parser, &found_cr);
3393   found_cr = 0;
3394   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3395       != XML_STATUS_OK)
3396     xml_failure(g_parser);
3397   if (found_cr == 0)
3398     fail("No carriage return found");
3399 }
3400 END_TEST
3401 
3402 /* Test handling of trailing square bracket */
3403 static void XMLCALL
rsqb_handler(void * userData,const XML_Char * s,int len)3404 rsqb_handler(void *userData, const XML_Char *s, int len) {
3405   int *pfound = (int *)userData;
3406 
3407   if (len == 1 && *s == XCS(']'))
3408     *pfound = 1;
3409 }
3410 
START_TEST(test_trailing_rsqb)3411 START_TEST(test_trailing_rsqb) {
3412   const char *text8 = "<doc>]";
3413   const char text16[] = "\xFF\xFE<\000d\000o\000c\000>\000]\000";
3414   int found_rsqb;
3415   int text8_len = (int)strlen(text8);
3416 
3417   XML_SetCharacterDataHandler(g_parser, rsqb_handler);
3418   XML_SetUserData(g_parser, &found_rsqb);
3419   found_rsqb = 0;
3420   if (_XML_Parse_SINGLE_BYTES(g_parser, text8, text8_len, XML_TRUE)
3421       == XML_STATUS_OK)
3422     fail("Failed to fault unclosed doc");
3423   if (found_rsqb == 0)
3424     fail("Did not catch the right square bracket");
3425 
3426   /* Try again with a different encoding */
3427   XML_ParserReset(g_parser, NULL);
3428   XML_SetCharacterDataHandler(g_parser, rsqb_handler);
3429   XML_SetUserData(g_parser, &found_rsqb);
3430   found_rsqb = 0;
3431   if (_XML_Parse_SINGLE_BYTES(g_parser, text16, (int)sizeof(text16) - 1,
3432                               XML_TRUE)
3433       == XML_STATUS_OK)
3434     fail("Failed to fault unclosed doc");
3435   if (found_rsqb == 0)
3436     fail("Did not catch the right square bracket");
3437 
3438   /* And finally with a default handler */
3439   XML_ParserReset(g_parser, NULL);
3440   XML_SetDefaultHandler(g_parser, rsqb_handler);
3441   XML_SetUserData(g_parser, &found_rsqb);
3442   found_rsqb = 0;
3443   if (_XML_Parse_SINGLE_BYTES(g_parser, text16, (int)sizeof(text16) - 1,
3444                               XML_TRUE)
3445       == XML_STATUS_OK)
3446     fail("Failed to fault unclosed doc");
3447   if (found_rsqb == 0)
3448     fail("Did not catch the right square bracket");
3449 }
3450 END_TEST
3451 
3452 /* Test trailing right square bracket in an external entity parse */
3453 static int XMLCALL
external_entity_rsqb_catcher(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3454 external_entity_rsqb_catcher(XML_Parser parser, const XML_Char *context,
3455                              const XML_Char *base, const XML_Char *systemId,
3456                              const XML_Char *publicId) {
3457   const char *text = "<tag>]";
3458   XML_Parser ext_parser;
3459 
3460   UNUSED_P(base);
3461   UNUSED_P(systemId);
3462   UNUSED_P(publicId);
3463   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3464   if (ext_parser == NULL)
3465     fail("Could not create external entity parser");
3466   XML_SetCharacterDataHandler(ext_parser, rsqb_handler);
3467   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3468       != XML_STATUS_ERROR)
3469     fail("Async entity error not caught");
3470   if (XML_GetErrorCode(ext_parser) != XML_ERROR_ASYNC_ENTITY)
3471     xml_failure(ext_parser);
3472   XML_ParserFree(ext_parser);
3473   return XML_STATUS_OK;
3474 }
3475 
START_TEST(test_ext_entity_trailing_rsqb)3476 START_TEST(test_ext_entity_trailing_rsqb) {
3477   const char *text = "<!DOCTYPE doc [\n"
3478                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
3479                      "]>\n"
3480                      "<doc>&en;</doc>";
3481   int found_rsqb;
3482 
3483   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3484   XML_SetExternalEntityRefHandler(g_parser, external_entity_rsqb_catcher);
3485   XML_SetUserData(g_parser, &found_rsqb);
3486   found_rsqb = 0;
3487   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3488       != XML_STATUS_OK)
3489     xml_failure(g_parser);
3490   if (found_rsqb == 0)
3491     fail("No right square bracket found");
3492 }
3493 END_TEST
3494 
3495 /* Test CDATA handling in an external entity */
3496 static int XMLCALL
external_entity_good_cdata_ascii(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3497 external_entity_good_cdata_ascii(XML_Parser parser, const XML_Char *context,
3498                                  const XML_Char *base, const XML_Char *systemId,
3499                                  const XML_Char *publicId) {
3500   const char *text = "<a><![CDATA[<greeting>Hello, world!</greeting>]]></a>";
3501   const XML_Char *expected = XCS("<greeting>Hello, world!</greeting>");
3502   CharData storage;
3503   XML_Parser ext_parser;
3504 
3505   UNUSED_P(base);
3506   UNUSED_P(systemId);
3507   UNUSED_P(publicId);
3508   CharData_Init(&storage);
3509   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3510   if (ext_parser == NULL)
3511     fail("Could not create external entity parser");
3512   XML_SetUserData(ext_parser, &storage);
3513   XML_SetCharacterDataHandler(ext_parser, accumulate_characters);
3514 
3515   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3516       == XML_STATUS_ERROR)
3517     xml_failure(ext_parser);
3518   CharData_CheckXMLChars(&storage, expected);
3519 
3520   XML_ParserFree(ext_parser);
3521   return XML_STATUS_OK;
3522 }
3523 
START_TEST(test_ext_entity_good_cdata)3524 START_TEST(test_ext_entity_good_cdata) {
3525   const char *text = "<!DOCTYPE doc [\n"
3526                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
3527                      "]>\n"
3528                      "<doc>&en;</doc>";
3529 
3530   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3531   XML_SetExternalEntityRefHandler(g_parser, external_entity_good_cdata_ascii);
3532   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3533       != XML_STATUS_OK)
3534     xml_failure(g_parser);
3535 }
3536 END_TEST
3537 
3538 /* Test user parameter settings */
3539 /* Variable holding the expected handler userData */
3540 static void *handler_data = NULL;
3541 /* Count of the number of times the comment handler has been invoked */
3542 static int comment_count = 0;
3543 /* Count of the number of skipped entities */
3544 static int skip_count = 0;
3545 /* Count of the number of times the XML declaration handler is invoked */
3546 static int xdecl_count = 0;
3547 
3548 static void XMLCALL
xml_decl_handler(void * userData,const XML_Char * version,const XML_Char * encoding,int standalone)3549 xml_decl_handler(void *userData, const XML_Char *version,
3550                  const XML_Char *encoding, int standalone) {
3551   UNUSED_P(version);
3552   UNUSED_P(encoding);
3553   if (userData != handler_data)
3554     fail("User data (xml decl) not correctly set");
3555   if (standalone != -1)
3556     fail("Standalone not flagged as not present in XML decl");
3557   xdecl_count++;
3558 }
3559 
3560 static void XMLCALL
param_check_skip_handler(void * userData,const XML_Char * entityName,int is_parameter_entity)3561 param_check_skip_handler(void *userData, const XML_Char *entityName,
3562                          int is_parameter_entity) {
3563   UNUSED_P(entityName);
3564   UNUSED_P(is_parameter_entity);
3565   if (userData != handler_data)
3566     fail("User data (skip) not correctly set");
3567   skip_count++;
3568 }
3569 
3570 static void XMLCALL
data_check_comment_handler(void * userData,const XML_Char * data)3571 data_check_comment_handler(void *userData, const XML_Char *data) {
3572   UNUSED_P(data);
3573   /* Check that the userData passed through is what we expect */
3574   if (userData != handler_data)
3575     fail("User data (parser) not correctly set");
3576   /* Check that the user data in the parser is appropriate */
3577   if (XML_GetUserData(userData) != (void *)1)
3578     fail("User data in parser not correctly set");
3579   comment_count++;
3580 }
3581 
3582 static int XMLCALL
external_entity_param_checker(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3583 external_entity_param_checker(XML_Parser parser, const XML_Char *context,
3584                               const XML_Char *base, const XML_Char *systemId,
3585                               const XML_Char *publicId) {
3586   const char *text = "<!-- Subordinate parser -->\n"
3587                      "<!ELEMENT doc (#PCDATA)*>";
3588   XML_Parser ext_parser;
3589 
3590   UNUSED_P(base);
3591   UNUSED_P(systemId);
3592   UNUSED_P(publicId);
3593   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3594   if (ext_parser == NULL)
3595     fail("Could not create external entity parser");
3596   handler_data = ext_parser;
3597   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3598       == XML_STATUS_ERROR) {
3599     xml_failure(parser);
3600     return XML_STATUS_ERROR;
3601   }
3602   handler_data = parser;
3603   XML_ParserFree(ext_parser);
3604   return XML_STATUS_OK;
3605 }
3606 
START_TEST(test_user_parameters)3607 START_TEST(test_user_parameters) {
3608   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
3609                      "<!-- Primary parse -->\n"
3610                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
3611                      "<doc>&entity;";
3612   const char *epilog = "<!-- Back to primary parser -->\n"
3613                        "</doc>";
3614 
3615   comment_count = 0;
3616   skip_count = 0;
3617   xdecl_count = 0;
3618   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3619   XML_SetXmlDeclHandler(g_parser, xml_decl_handler);
3620   XML_SetExternalEntityRefHandler(g_parser, external_entity_param_checker);
3621   XML_SetCommentHandler(g_parser, data_check_comment_handler);
3622   XML_SetSkippedEntityHandler(g_parser, param_check_skip_handler);
3623   XML_UseParserAsHandlerArg(g_parser);
3624   XML_SetUserData(g_parser, (void *)1);
3625   handler_data = g_parser;
3626   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
3627       == XML_STATUS_ERROR)
3628     xml_failure(g_parser);
3629   if (comment_count != 2)
3630     fail("Comment handler not invoked enough times");
3631   /* Ensure we can't change policy mid-parse */
3632   if (XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_NEVER))
3633     fail("Changed param entity parsing policy while parsing");
3634   if (_XML_Parse_SINGLE_BYTES(g_parser, epilog, (int)strlen(epilog), XML_TRUE)
3635       == XML_STATUS_ERROR)
3636     xml_failure(g_parser);
3637   if (comment_count != 3)
3638     fail("Comment handler not invoked enough times");
3639   if (skip_count != 1)
3640     fail("Skip handler not invoked enough times");
3641   if (xdecl_count != 1)
3642     fail("XML declaration handler not invoked");
3643 }
3644 END_TEST
3645 
3646 /* Test that an explicit external entity handler argument replaces
3647  * the parser as the first argument.
3648  *
3649  * We do not call the first parameter to the external entity handler
3650  * 'parser' for once, since the first time the handler is called it
3651  * will actually be a text string.  We need to be able to access the
3652  * global 'parser' variable to create our external entity parser from,
3653  * since there are code paths we need to ensure get executed.
3654  */
3655 static int XMLCALL
external_entity_ref_param_checker(XML_Parser parameter,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3656 external_entity_ref_param_checker(XML_Parser parameter, const XML_Char *context,
3657                                   const XML_Char *base,
3658                                   const XML_Char *systemId,
3659                                   const XML_Char *publicId) {
3660   const char *text = "<!ELEMENT doc (#PCDATA)*>";
3661   XML_Parser ext_parser;
3662 
3663   UNUSED_P(base);
3664   UNUSED_P(systemId);
3665   UNUSED_P(publicId);
3666   if ((void *)parameter != handler_data)
3667     fail("External entity ref handler parameter not correct");
3668 
3669   /* Here we use the global 'parser' variable */
3670   ext_parser = XML_ExternalEntityParserCreate(g_parser, context, NULL);
3671   if (ext_parser == NULL)
3672     fail("Could not create external entity parser");
3673   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3674       == XML_STATUS_ERROR)
3675     xml_failure(ext_parser);
3676 
3677   XML_ParserFree(ext_parser);
3678   return XML_STATUS_OK;
3679 }
3680 
START_TEST(test_ext_entity_ref_parameter)3681 START_TEST(test_ext_entity_ref_parameter) {
3682   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
3683                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
3684                      "<doc>&entity;</doc>";
3685 
3686   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3687   XML_SetExternalEntityRefHandler(g_parser, external_entity_ref_param_checker);
3688   /* Set a handler arg that is not NULL and not parser (which is
3689    * what NULL would cause to be passed.
3690    */
3691   XML_SetExternalEntityRefHandlerArg(g_parser, (void *)text);
3692   handler_data = (void *)text;
3693   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3694       == XML_STATUS_ERROR)
3695     xml_failure(g_parser);
3696 
3697   /* Now try again with unset args */
3698   XML_ParserReset(g_parser, NULL);
3699   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3700   XML_SetExternalEntityRefHandler(g_parser, external_entity_ref_param_checker);
3701   XML_SetExternalEntityRefHandlerArg(g_parser, NULL);
3702   handler_data = (void *)g_parser;
3703   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3704       == XML_STATUS_ERROR)
3705     xml_failure(g_parser);
3706 }
3707 END_TEST
3708 
3709 /* Test the parsing of an empty string */
START_TEST(test_empty_parse)3710 START_TEST(test_empty_parse) {
3711   const char *text = "<doc></doc>";
3712   const char *partial = "<doc>";
3713 
3714   if (XML_Parse(g_parser, NULL, 0, XML_FALSE) == XML_STATUS_ERROR)
3715     fail("Parsing empty string faulted");
3716   if (XML_Parse(g_parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR)
3717     fail("Parsing final empty string not faulted");
3718   if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_ELEMENTS)
3719     fail("Parsing final empty string faulted for wrong reason");
3720 
3721   /* Now try with valid text before the empty end */
3722   XML_ParserReset(g_parser, NULL);
3723   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
3724       == XML_STATUS_ERROR)
3725     xml_failure(g_parser);
3726   if (XML_Parse(g_parser, NULL, 0, XML_TRUE) == XML_STATUS_ERROR)
3727     fail("Parsing final empty string faulted");
3728 
3729   /* Now try with invalid text before the empty end */
3730   XML_ParserReset(g_parser, NULL);
3731   if (_XML_Parse_SINGLE_BYTES(g_parser, partial, (int)strlen(partial),
3732                               XML_FALSE)
3733       == XML_STATUS_ERROR)
3734     xml_failure(g_parser);
3735   if (XML_Parse(g_parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR)
3736     fail("Parsing final incomplete empty string not faulted");
3737 }
3738 END_TEST
3739 
3740 /* Test XML_Parse for len < 0 */
START_TEST(test_negative_len_parse)3741 START_TEST(test_negative_len_parse) {
3742   const char *const doc = "<root/>";
3743   for (int isFinal = 0; isFinal < 2; isFinal++) {
3744     set_subtest("isFinal=%d", isFinal);
3745 
3746     XML_Parser parser = XML_ParserCreate(NULL);
3747 
3748     if (XML_GetErrorCode(parser) != XML_ERROR_NONE)
3749       fail("There was not supposed to be any initial parse error.");
3750 
3751     const enum XML_Status status = XML_Parse(parser, doc, -1, isFinal);
3752 
3753     if (status != XML_STATUS_ERROR)
3754       fail("Negative len was expected to fail the parse but did not.");
3755 
3756     if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_ARGUMENT)
3757       fail("Parse error does not match XML_ERROR_INVALID_ARGUMENT.");
3758 
3759     XML_ParserFree(parser);
3760   }
3761 }
3762 END_TEST
3763 
3764 /* Test XML_ParseBuffer for len < 0 */
START_TEST(test_negative_len_parse_buffer)3765 START_TEST(test_negative_len_parse_buffer) {
3766   const char *const doc = "<root/>";
3767   for (int isFinal = 0; isFinal < 2; isFinal++) {
3768     set_subtest("isFinal=%d", isFinal);
3769 
3770     XML_Parser parser = XML_ParserCreate(NULL);
3771 
3772     if (XML_GetErrorCode(parser) != XML_ERROR_NONE)
3773       fail("There was not supposed to be any initial parse error.");
3774 
3775     void *const buffer = XML_GetBuffer(parser, (int)strlen(doc));
3776 
3777     if (buffer == NULL)
3778       fail("XML_GetBuffer failed.");
3779 
3780     memcpy(buffer, doc, strlen(doc));
3781 
3782     const enum XML_Status status = XML_ParseBuffer(parser, -1, isFinal);
3783 
3784     if (status != XML_STATUS_ERROR)
3785       fail("Negative len was expected to fail the parse but did not.");
3786 
3787     if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_ARGUMENT)
3788       fail("Parse error does not match XML_ERROR_INVALID_ARGUMENT.");
3789 
3790     XML_ParserFree(parser);
3791   }
3792 }
3793 END_TEST
3794 
3795 /* Test odd corners of the XML_GetBuffer interface */
3796 static enum XML_Status
get_feature(enum XML_FeatureEnum feature_id,long * presult)3797 get_feature(enum XML_FeatureEnum feature_id, long *presult) {
3798   const XML_Feature *feature = XML_GetFeatureList();
3799 
3800   if (feature == NULL)
3801     return XML_STATUS_ERROR;
3802   for (; feature->feature != XML_FEATURE_END; feature++) {
3803     if (feature->feature == feature_id) {
3804       *presult = feature->value;
3805       return XML_STATUS_OK;
3806     }
3807   }
3808   return XML_STATUS_ERROR;
3809 }
3810 
3811 /* Having an element name longer than 1024 characters exercises some
3812  * of the pool allocation code in the parser that otherwise does not
3813  * get executed.  The count at the end of the line is the number of
3814  * characters (bytes) in the element name by that point.x
3815  */
3816 static const char *get_buffer_test_text
3817     = "<documentwitharidiculouslylongelementnametotease"  /* 0x030 */
3818       "aparticularcorneroftheallocationinXML_GetBuffers"  /* 0x060 */
3819       "othatwecanimprovethecoverageyetagain012345678901"  /* 0x090 */
3820       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x0c0 */
3821       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x0f0 */
3822       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x120 */
3823       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x150 */
3824       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x180 */
3825       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x1b0 */
3826       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x1e0 */
3827       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x210 */
3828       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x240 */
3829       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x270 */
3830       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x2a0 */
3831       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x2d0 */
3832       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x300 */
3833       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x330 */
3834       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x360 */
3835       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x390 */
3836       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x3c0 */
3837       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x3f0 */
3838       "123456789abcdef0123456789abcdef0123456789>\n<ef0"; /* 0x420 */
3839 
3840 /* Test odd corners of the XML_GetBuffer interface */
START_TEST(test_get_buffer_1)3841 START_TEST(test_get_buffer_1) {
3842   const char *text = get_buffer_test_text;
3843   void *buffer;
3844   long context_bytes;
3845 
3846   /* Attempt to allocate a negative length buffer */
3847   if (XML_GetBuffer(g_parser, -12) != NULL)
3848     fail("Negative length buffer not failed");
3849 
3850   /* Now get a small buffer and extend it past valid length */
3851   buffer = XML_GetBuffer(g_parser, 1536);
3852   if (buffer == NULL)
3853     fail("1.5K buffer failed");
3854   assert(buffer != NULL);
3855   memcpy(buffer, text, strlen(text));
3856   if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE)
3857       == XML_STATUS_ERROR)
3858     xml_failure(g_parser);
3859   if (XML_GetBuffer(g_parser, INT_MAX) != NULL)
3860     fail("INT_MAX buffer not failed");
3861 
3862   /* Now try extending it a more reasonable but still too large
3863    * amount.  The allocator in XML_GetBuffer() doubles the buffer
3864    * size until it exceeds the requested amount or INT_MAX.  If it
3865    * exceeds INT_MAX, it rejects the request, so we want a request
3866    * between INT_MAX and INT_MAX/2.  A gap of 1K seems comfortable,
3867    * with an extra byte just to ensure that the request is off any
3868    * boundary.  The request will be inflated internally by
3869    * XML_CONTEXT_BYTES (if defined), so we subtract that from our
3870    * request.
3871    */
3872   if (get_feature(XML_FEATURE_CONTEXT_BYTES, &context_bytes) != XML_STATUS_OK)
3873     context_bytes = 0;
3874   if (XML_GetBuffer(g_parser, INT_MAX - (context_bytes + 1025)) != NULL)
3875     fail("INT_MAX- buffer not failed");
3876 
3877   /* Now try extending it a carefully crafted amount */
3878   if (XML_GetBuffer(g_parser, 1000) == NULL)
3879     fail("1000 buffer failed");
3880 }
3881 END_TEST
3882 
3883 /* Test more corners of the XML_GetBuffer interface */
START_TEST(test_get_buffer_2)3884 START_TEST(test_get_buffer_2) {
3885   const char *text = get_buffer_test_text;
3886   void *buffer;
3887 
3888   /* Now get a decent buffer */
3889   buffer = XML_GetBuffer(g_parser, 1536);
3890   if (buffer == NULL)
3891     fail("1.5K buffer failed");
3892   assert(buffer != NULL);
3893   memcpy(buffer, text, strlen(text));
3894   if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE)
3895       == XML_STATUS_ERROR)
3896     xml_failure(g_parser);
3897 
3898   /* Extend it, to catch a different code path */
3899   if (XML_GetBuffer(g_parser, 1024) == NULL)
3900     fail("1024 buffer failed");
3901 }
3902 END_TEST
3903 
3904 /* Test position information macros */
START_TEST(test_byte_info_at_end)3905 START_TEST(test_byte_info_at_end) {
3906   const char *text = "<doc></doc>";
3907 
3908   if (XML_GetCurrentByteIndex(g_parser) != -1
3909       || XML_GetCurrentByteCount(g_parser) != 0)
3910     fail("Byte index/count incorrect at start of parse");
3911   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3912       == XML_STATUS_ERROR)
3913     xml_failure(g_parser);
3914   /* At end, the count will be zero and the index the end of string */
3915   if (XML_GetCurrentByteCount(g_parser) != 0)
3916     fail("Terminal byte count incorrect");
3917   if (XML_GetCurrentByteIndex(g_parser) != (XML_Index)strlen(text))
3918     fail("Terminal byte index incorrect");
3919 }
3920 END_TEST
3921 
3922 /* Test position information from errors */
3923 #define PRE_ERROR_STR "<doc></"
3924 #define POST_ERROR_STR "wombat></doc>"
START_TEST(test_byte_info_at_error)3925 START_TEST(test_byte_info_at_error) {
3926   const char *text = PRE_ERROR_STR POST_ERROR_STR;
3927 
3928   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3929       == XML_STATUS_OK)
3930     fail("Syntax error not faulted");
3931   if (XML_GetCurrentByteCount(g_parser) != 0)
3932     fail("Error byte count incorrect");
3933   if (XML_GetCurrentByteIndex(g_parser) != strlen(PRE_ERROR_STR))
3934     fail("Error byte index incorrect");
3935 }
3936 END_TEST
3937 #undef PRE_ERROR_STR
3938 #undef POST_ERROR_STR
3939 
3940 /* Test position information in handler */
3941 typedef struct ByteTestData {
3942   int start_element_len;
3943   int cdata_len;
3944   int total_string_len;
3945 } ByteTestData;
3946 
3947 static void
byte_character_handler(void * userData,const XML_Char * s,int len)3948 byte_character_handler(void *userData, const XML_Char *s, int len) {
3949 #ifdef XML_CONTEXT_BYTES
3950   int offset, size;
3951   const char *buffer;
3952   ByteTestData *data = (ByteTestData *)userData;
3953 
3954   UNUSED_P(s);
3955   buffer = XML_GetInputContext(g_parser, &offset, &size);
3956   if (buffer == NULL)
3957     fail("Failed to get context buffer");
3958   if (offset != data->start_element_len)
3959     fail("Context offset in unexpected position");
3960   if (len != data->cdata_len)
3961     fail("CDATA length reported incorrectly");
3962   if (size != data->total_string_len)
3963     fail("Context size is not full buffer");
3964   if (XML_GetCurrentByteIndex(g_parser) != offset)
3965     fail("Character byte index incorrect");
3966   if (XML_GetCurrentByteCount(g_parser) != len)
3967     fail("Character byte count incorrect");
3968 #else
3969   UNUSED_P(s);
3970   UNUSED_P(userData);
3971   UNUSED_P(len);
3972 #endif
3973 }
3974 
3975 #define START_ELEMENT "<e>"
3976 #define CDATA_TEXT "Hello"
3977 #define END_ELEMENT "</e>"
START_TEST(test_byte_info_at_cdata)3978 START_TEST(test_byte_info_at_cdata) {
3979   const char *text = START_ELEMENT CDATA_TEXT END_ELEMENT;
3980   int offset, size;
3981   ByteTestData data;
3982 
3983   /* Check initial context is empty */
3984   if (XML_GetInputContext(g_parser, &offset, &size) != NULL)
3985     fail("Unexpected context at start of parse");
3986 
3987   data.start_element_len = (int)strlen(START_ELEMENT);
3988   data.cdata_len = (int)strlen(CDATA_TEXT);
3989   data.total_string_len = (int)strlen(text);
3990   XML_SetCharacterDataHandler(g_parser, byte_character_handler);
3991   XML_SetUserData(g_parser, &data);
3992   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_OK)
3993     xml_failure(g_parser);
3994 }
3995 END_TEST
3996 #undef START_ELEMENT
3997 #undef CDATA_TEXT
3998 #undef END_ELEMENT
3999 
4000 /* Test predefined entities are correctly recognised */
START_TEST(test_predefined_entities)4001 START_TEST(test_predefined_entities) {
4002   const char *text = "<doc>&lt;&gt;&amp;&quot;&apos;</doc>";
4003   const XML_Char *expected = XCS("<doc>&lt;&gt;&amp;&quot;&apos;</doc>");
4004   const XML_Char *result = XCS("<>&\"'");
4005   CharData storage;
4006 
4007   XML_SetDefaultHandler(g_parser, accumulate_characters);
4008   /* run_character_check uses XML_SetCharacterDataHandler(), which
4009    * unfortunately heads off a code path that we need to exercise.
4010    */
4011   CharData_Init(&storage);
4012   XML_SetUserData(g_parser, &storage);
4013   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4014       == XML_STATUS_ERROR)
4015     xml_failure(g_parser);
4016   /* The default handler doesn't translate the entities */
4017   CharData_CheckXMLChars(&storage, expected);
4018 
4019   /* Now try again and check the translation */
4020   XML_ParserReset(g_parser, NULL);
4021   run_character_check(text, result);
4022 }
4023 END_TEST
4024 
4025 /* Regression test that an invalid tag in an external parameter
4026  * reference in an external DTD is correctly faulted.
4027  *
4028  * Only a few specific tags are legal in DTDs ignoring comments and
4029  * processing instructions, all of which begin with an exclamation
4030  * mark.  "<el/>" is not one of them, so the parser should raise an
4031  * error on encountering it.
4032  */
4033 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)4034 external_entity_param(XML_Parser parser, const XML_Char *context,
4035                       const XML_Char *base, const XML_Char *systemId,
4036                       const XML_Char *publicId) {
4037   const char *text1 = "<!ELEMENT doc EMPTY>\n"
4038                       "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
4039                       "<!ENTITY % e2 '%e1;'>\n"
4040                       "%e1;\n";
4041   const char *text2 = "<!ELEMENT el EMPTY>\n"
4042                       "<el/>\n";
4043   XML_Parser ext_parser;
4044 
4045   UNUSED_P(base);
4046   UNUSED_P(publicId);
4047   if (systemId == NULL)
4048     return XML_STATUS_OK;
4049 
4050   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4051   if (ext_parser == NULL)
4052     fail("Could not create external entity parser");
4053 
4054   if (! xcstrcmp(systemId, XCS("004-1.ent"))) {
4055     if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
4056         != XML_STATUS_ERROR)
4057       fail("Inner DTD with invalid tag not rejected");
4058     if (XML_GetErrorCode(ext_parser) != XML_ERROR_EXTERNAL_ENTITY_HANDLING)
4059       xml_failure(ext_parser);
4060   } else if (! xcstrcmp(systemId, XCS("004-2.ent"))) {
4061     if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE)
4062         != XML_STATUS_ERROR)
4063       fail("Invalid tag in external param not rejected");
4064     if (XML_GetErrorCode(ext_parser) != XML_ERROR_SYNTAX)
4065       xml_failure(ext_parser);
4066   } else {
4067     fail("Unknown system ID");
4068   }
4069 
4070   XML_ParserFree(ext_parser);
4071   return XML_STATUS_ERROR;
4072 }
4073 
START_TEST(test_invalid_tag_in_dtd)4074 START_TEST(test_invalid_tag_in_dtd) {
4075   const char *text = "<!DOCTYPE doc SYSTEM '004-1.ent'>\n"
4076                      "<doc></doc>\n";
4077 
4078   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4079   XML_SetExternalEntityRefHandler(g_parser, external_entity_param);
4080   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
4081                  "Invalid tag IN DTD external param not rejected");
4082 }
4083 END_TEST
4084 
4085 /* Test entities not quite the predefined ones are not mis-recognised */
START_TEST(test_not_predefined_entities)4086 START_TEST(test_not_predefined_entities) {
4087   const char *text[] = {"<doc>&pt;</doc>", "<doc>&amo;</doc>",
4088                         "<doc>&quid;</doc>", "<doc>&apod;</doc>", NULL};
4089   int i = 0;
4090 
4091   while (text[i] != NULL) {
4092     expect_failure(text[i], XML_ERROR_UNDEFINED_ENTITY,
4093                    "Undefined entity not rejected");
4094     XML_ParserReset(g_parser, NULL);
4095     i++;
4096   }
4097 }
4098 END_TEST
4099 
4100 /* Test conditional inclusion (IGNORE) */
4101 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)4102 external_entity_load_ignore(XML_Parser parser, const XML_Char *context,
4103                             const XML_Char *base, const XML_Char *systemId,
4104                             const XML_Char *publicId) {
4105   const char *text = "<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>";
4106   XML_Parser ext_parser;
4107 
4108   UNUSED_P(base);
4109   UNUSED_P(systemId);
4110   UNUSED_P(publicId);
4111   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4112   if (ext_parser == NULL)
4113     fail("Could not create external entity parser");
4114   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
4115       == XML_STATUS_ERROR)
4116     xml_failure(parser);
4117 
4118   XML_ParserFree(ext_parser);
4119   return XML_STATUS_OK;
4120 }
4121 
START_TEST(test_ignore_section)4122 START_TEST(test_ignore_section) {
4123   const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
4124                      "<doc><e>&entity;</e></doc>";
4125   const XML_Char *expected
4126       = XCS("<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>\n&entity;");
4127   CharData storage;
4128 
4129   CharData_Init(&storage);
4130   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4131   XML_SetUserData(g_parser, &storage);
4132   XML_SetExternalEntityRefHandler(g_parser, external_entity_load_ignore);
4133   XML_SetDefaultHandler(g_parser, accumulate_characters);
4134   XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler);
4135   XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler);
4136   XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4137   XML_SetStartElementHandler(g_parser, dummy_start_element);
4138   XML_SetEndElementHandler(g_parser, dummy_end_element);
4139   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4140       == XML_STATUS_ERROR)
4141     xml_failure(g_parser);
4142   CharData_CheckXMLChars(&storage, expected);
4143 }
4144 END_TEST
4145 
4146 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)4147 external_entity_load_ignore_utf16(XML_Parser parser, const XML_Char *context,
4148                                   const XML_Char *base,
4149                                   const XML_Char *systemId,
4150                                   const XML_Char *publicId) {
4151   const char text[] =
4152       /* <![IGNORE[<!ELEMENT e (#PCDATA)*>]]> */
4153       "<\0!\0[\0I\0G\0N\0O\0R\0E\0[\0"
4154       "<\0!\0E\0L\0E\0M\0E\0N\0T\0 \0e\0 \0"
4155       "(\0#\0P\0C\0D\0A\0T\0A\0)\0*\0>\0]\0]\0>\0";
4156   XML_Parser ext_parser;
4157 
4158   UNUSED_P(base);
4159   UNUSED_P(systemId);
4160   UNUSED_P(publicId);
4161   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4162   if (ext_parser == NULL)
4163     fail("Could not create external entity parser");
4164   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)sizeof(text) - 1, XML_TRUE)
4165       == XML_STATUS_ERROR)
4166     xml_failure(parser);
4167 
4168   XML_ParserFree(ext_parser);
4169   return XML_STATUS_OK;
4170 }
4171 
START_TEST(test_ignore_section_utf16)4172 START_TEST(test_ignore_section_utf16) {
4173   const char text[] =
4174       /* <!DOCTYPE d SYSTEM 's'> */
4175       "<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 "
4176       "\0S\0Y\0S\0T\0E\0M\0 \0'\0s\0'\0>\0\n\0"
4177       /* <d><e>&en;</e></d> */
4178       "<\0d\0>\0<\0e\0>\0&\0e\0n\0;\0<\0/\0e\0>\0<\0/\0d\0>\0";
4179   const XML_Char *expected = XCS("<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>\n&en;");
4180   CharData storage;
4181 
4182   CharData_Init(&storage);
4183   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4184   XML_SetUserData(g_parser, &storage);
4185   XML_SetExternalEntityRefHandler(g_parser, external_entity_load_ignore_utf16);
4186   XML_SetDefaultHandler(g_parser, accumulate_characters);
4187   XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler);
4188   XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler);
4189   XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4190   XML_SetStartElementHandler(g_parser, dummy_start_element);
4191   XML_SetEndElementHandler(g_parser, dummy_end_element);
4192   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
4193       == XML_STATUS_ERROR)
4194     xml_failure(g_parser);
4195   CharData_CheckXMLChars(&storage, expected);
4196 }
4197 END_TEST
4198 
4199 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)4200 external_entity_load_ignore_utf16_be(XML_Parser parser, const XML_Char *context,
4201                                      const XML_Char *base,
4202                                      const XML_Char *systemId,
4203                                      const XML_Char *publicId) {
4204   const char text[] =
4205       /* <![IGNORE[<!ELEMENT e (#PCDATA)*>]]> */
4206       "\0<\0!\0[\0I\0G\0N\0O\0R\0E\0["
4207       "\0<\0!\0E\0L\0E\0M\0E\0N\0T\0 \0e\0 "
4208       "\0(\0#\0P\0C\0D\0A\0T\0A\0)\0*\0>\0]\0]\0>";
4209   XML_Parser ext_parser;
4210 
4211   UNUSED_P(base);
4212   UNUSED_P(systemId);
4213   UNUSED_P(publicId);
4214   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4215   if (ext_parser == NULL)
4216     fail("Could not create external entity parser");
4217   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)sizeof(text) - 1, XML_TRUE)
4218       == XML_STATUS_ERROR)
4219     xml_failure(parser);
4220 
4221   XML_ParserFree(ext_parser);
4222   return XML_STATUS_OK;
4223 }
4224 
START_TEST(test_ignore_section_utf16_be)4225 START_TEST(test_ignore_section_utf16_be) {
4226   const char text[] =
4227       /* <!DOCTYPE d SYSTEM 's'> */
4228       "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 "
4229       "\0S\0Y\0S\0T\0E\0M\0 \0'\0s\0'\0>\0\n"
4230       /* <d><e>&en;</e></d> */
4231       "\0<\0d\0>\0<\0e\0>\0&\0e\0n\0;\0<\0/\0e\0>\0<\0/\0d\0>";
4232   const XML_Char *expected = XCS("<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>\n&en;");
4233   CharData storage;
4234 
4235   CharData_Init(&storage);
4236   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4237   XML_SetUserData(g_parser, &storage);
4238   XML_SetExternalEntityRefHandler(g_parser,
4239                                   external_entity_load_ignore_utf16_be);
4240   XML_SetDefaultHandler(g_parser, accumulate_characters);
4241   XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler);
4242   XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler);
4243   XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4244   XML_SetStartElementHandler(g_parser, dummy_start_element);
4245   XML_SetEndElementHandler(g_parser, dummy_end_element);
4246   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
4247       == XML_STATUS_ERROR)
4248     xml_failure(g_parser);
4249   CharData_CheckXMLChars(&storage, expected);
4250 }
4251 END_TEST
4252 
4253 /* Test mis-formatted conditional exclusion */
START_TEST(test_bad_ignore_section)4254 START_TEST(test_bad_ignore_section) {
4255   const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
4256                      "<doc><e>&entity;</e></doc>";
4257   ExtFaults faults[]
4258       = {{"<![IGNORE[<!ELEM", "Broken-off declaration not faulted", NULL,
4259           XML_ERROR_SYNTAX},
4260          {"<![IGNORE[\x01]]>", "Invalid XML character not faulted", NULL,
4261           XML_ERROR_INVALID_TOKEN},
4262          {/* FIrst two bytes of a three-byte char */
4263           "<![IGNORE[\xe2\x82", "Partial XML character not faulted", NULL,
4264           XML_ERROR_PARTIAL_CHAR},
4265          {NULL, NULL, NULL, XML_ERROR_NONE}};
4266   ExtFaults *fault;
4267 
4268   for (fault = &faults[0]; fault->parse_text != NULL; fault++) {
4269     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4270     XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
4271     XML_SetUserData(g_parser, fault);
4272     expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
4273                    "Incomplete IGNORE section not failed");
4274     XML_ParserReset(g_parser, NULL);
4275   }
4276 }
4277 END_TEST
4278 
4279 /* Test recursive parsing */
4280 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)4281 external_entity_valuer(XML_Parser parser, const XML_Char *context,
4282                        const XML_Char *base, const XML_Char *systemId,
4283                        const XML_Char *publicId) {
4284   const char *text1 = "<!ELEMENT doc EMPTY>\n"
4285                       "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
4286                       "<!ENTITY % e2 '%e1;'>\n"
4287                       "%e1;\n";
4288   XML_Parser ext_parser;
4289 
4290   UNUSED_P(base);
4291   UNUSED_P(publicId);
4292   if (systemId == NULL)
4293     return XML_STATUS_OK;
4294   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4295   if (ext_parser == NULL)
4296     fail("Could not create external entity parser");
4297   if (! xcstrcmp(systemId, XCS("004-1.ent"))) {
4298     if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
4299         == XML_STATUS_ERROR)
4300       xml_failure(ext_parser);
4301   } else if (! xcstrcmp(systemId, XCS("004-2.ent"))) {
4302     ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser);
4303     enum XML_Status status;
4304     enum XML_Error error;
4305 
4306     status = _XML_Parse_SINGLE_BYTES(ext_parser, fault->parse_text,
4307                                      (int)strlen(fault->parse_text), XML_TRUE);
4308     if (fault->error == XML_ERROR_NONE) {
4309       if (status == XML_STATUS_ERROR)
4310         xml_failure(ext_parser);
4311     } else {
4312       if (status != XML_STATUS_ERROR)
4313         fail(fault->fail_text);
4314       error = XML_GetErrorCode(ext_parser);
4315       if (error != fault->error
4316           && (fault->error != XML_ERROR_XML_DECL
4317               || error != XML_ERROR_TEXT_DECL))
4318         xml_failure(ext_parser);
4319     }
4320   }
4321 
4322   XML_ParserFree(ext_parser);
4323   return XML_STATUS_OK;
4324 }
4325 
START_TEST(test_external_entity_values)4326 START_TEST(test_external_entity_values) {
4327   const char *text = "<!DOCTYPE doc SYSTEM '004-1.ent'>\n"
4328                      "<doc></doc>\n";
4329   ExtFaults data_004_2[] = {
4330       {"<!ATTLIST doc a1 CDATA 'value'>", NULL, NULL, XML_ERROR_NONE},
4331       {"<!ATTLIST $doc a1 CDATA 'value'>", "Invalid token not faulted", NULL,
4332        XML_ERROR_INVALID_TOKEN},
4333       {"'wombat", "Unterminated string not faulted", NULL,
4334        XML_ERROR_UNCLOSED_TOKEN},
4335       {"\xe2\x82", "Partial UTF-8 character not faulted", NULL,
4336        XML_ERROR_PARTIAL_CHAR},
4337       {"<?xml version='1.0' encoding='utf-8'?>\n", NULL, NULL, XML_ERROR_NONE},
4338       {"<?xml?>", "Malformed XML declaration not faulted", NULL,
4339        XML_ERROR_XML_DECL},
4340       {/* UTF-8 BOM */
4341        "\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>", NULL, NULL,
4342        XML_ERROR_NONE},
4343       {"<?xml version='1.0' encoding='utf-8'?>\n$",
4344        "Invalid token after text declaration not faulted", NULL,
4345        XML_ERROR_INVALID_TOKEN},
4346       {"<?xml version='1.0' encoding='utf-8'?>\n'wombat",
4347        "Unterminated string after text decl not faulted", NULL,
4348        XML_ERROR_UNCLOSED_TOKEN},
4349       {"<?xml version='1.0' encoding='utf-8'?>\n\xe2\x82",
4350        "Partial UTF-8 character after text decl not faulted", NULL,
4351        XML_ERROR_PARTIAL_CHAR},
4352       {"%e1;", "Recursive parameter entity not faulted", NULL,
4353        XML_ERROR_RECURSIVE_ENTITY_REF},
4354       {NULL, NULL, NULL, XML_ERROR_NONE}};
4355   int i;
4356 
4357   for (i = 0; data_004_2[i].parse_text != NULL; i++) {
4358     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4359     XML_SetExternalEntityRefHandler(g_parser, external_entity_valuer);
4360     XML_SetUserData(g_parser, &data_004_2[i]);
4361     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4362         == XML_STATUS_ERROR)
4363       xml_failure(g_parser);
4364     XML_ParserReset(g_parser, NULL);
4365   }
4366 }
4367 END_TEST
4368 
4369 /* Test the recursive parse interacts with a not standalone handler */
4370 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)4371 external_entity_not_standalone(XML_Parser parser, const XML_Char *context,
4372                                const XML_Char *base, const XML_Char *systemId,
4373                                const XML_Char *publicId) {
4374   const char *text1 = "<!ELEMENT doc EMPTY>\n"
4375                       "<!ENTITY % e1 SYSTEM 'bar'>\n"
4376                       "%e1;\n";
4377   const char *text2 = "<!ATTLIST doc a1 CDATA 'value'>";
4378   XML_Parser ext_parser;
4379 
4380   UNUSED_P(base);
4381   UNUSED_P(publicId);
4382   if (systemId == NULL)
4383     return XML_STATUS_OK;
4384   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4385   if (ext_parser == NULL)
4386     fail("Could not create external entity parser");
4387   if (! xcstrcmp(systemId, XCS("foo"))) {
4388     XML_SetNotStandaloneHandler(ext_parser, reject_not_standalone_handler);
4389     if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
4390         != XML_STATUS_ERROR)
4391       fail("Expected not standalone rejection");
4392     if (XML_GetErrorCode(ext_parser) != XML_ERROR_NOT_STANDALONE)
4393       xml_failure(ext_parser);
4394     XML_SetNotStandaloneHandler(ext_parser, NULL);
4395     XML_ParserFree(ext_parser);
4396     return XML_STATUS_ERROR;
4397   } else if (! xcstrcmp(systemId, XCS("bar"))) {
4398     if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE)
4399         == XML_STATUS_ERROR)
4400       xml_failure(ext_parser);
4401   }
4402 
4403   XML_ParserFree(ext_parser);
4404   return XML_STATUS_OK;
4405 }
4406 
START_TEST(test_ext_entity_not_standalone)4407 START_TEST(test_ext_entity_not_standalone) {
4408   const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
4409                      "<doc></doc>";
4410 
4411   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4412   XML_SetExternalEntityRefHandler(g_parser, external_entity_not_standalone);
4413   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
4414                  "Standalone rejection not caught");
4415 }
4416 END_TEST
4417 
4418 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)4419 external_entity_value_aborter(XML_Parser parser, const XML_Char *context,
4420                               const XML_Char *base, const XML_Char *systemId,
4421                               const XML_Char *publicId) {
4422   const char *text1 = "<!ELEMENT doc EMPTY>\n"
4423                       "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
4424                       "<!ENTITY % e2 '%e1;'>\n"
4425                       "%e1;\n";
4426   const char *text2 = "<?xml version='1.0' encoding='utf-8'?>";
4427   XML_Parser ext_parser;
4428 
4429   UNUSED_P(base);
4430   UNUSED_P(publicId);
4431   if (systemId == NULL)
4432     return XML_STATUS_OK;
4433   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4434   if (ext_parser == NULL)
4435     fail("Could not create external entity parser");
4436   if (! xcstrcmp(systemId, XCS("004-1.ent"))) {
4437     if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
4438         == XML_STATUS_ERROR)
4439       xml_failure(ext_parser);
4440   }
4441   if (! xcstrcmp(systemId, XCS("004-2.ent"))) {
4442     XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
4443     XML_SetUserData(ext_parser, ext_parser);
4444     if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE)
4445         != XML_STATUS_ERROR)
4446       fail("Aborted parse not faulted");
4447     if (XML_GetErrorCode(ext_parser) != XML_ERROR_ABORTED)
4448       xml_failure(ext_parser);
4449   }
4450 
4451   XML_ParserFree(ext_parser);
4452   return XML_STATUS_OK;
4453 }
4454 
START_TEST(test_ext_entity_value_abort)4455 START_TEST(test_ext_entity_value_abort) {
4456   const char *text = "<!DOCTYPE doc SYSTEM '004-1.ent'>\n"
4457                      "<doc></doc>\n";
4458 
4459   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4460   XML_SetExternalEntityRefHandler(g_parser, external_entity_value_aborter);
4461   resumable = XML_FALSE;
4462   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4463       == XML_STATUS_ERROR)
4464     xml_failure(g_parser);
4465 }
4466 END_TEST
4467 
START_TEST(test_bad_public_doctype)4468 START_TEST(test_bad_public_doctype) {
4469   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
4470                      "<!DOCTYPE doc PUBLIC '{BadName}' 'test'>\n"
4471                      "<doc></doc>";
4472 
4473   /* Setting a handler provokes a particular code path */
4474   XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_handler,
4475                             dummy_end_doctype_handler);
4476   expect_failure(text, XML_ERROR_PUBLICID, "Bad Public ID not failed");
4477 }
4478 END_TEST
4479 
4480 /* Test based on ibm/valid/P32/ibm32v04.xml */
START_TEST(test_attribute_enum_value)4481 START_TEST(test_attribute_enum_value) {
4482   const char *text = "<?xml version='1.0' standalone='no'?>\n"
4483                      "<!DOCTYPE animal SYSTEM 'test.dtd'>\n"
4484                      "<animal>This is a \n    <a/>  \n\nyellow tiger</animal>";
4485   ExtTest dtd_data
4486       = {"<!ELEMENT animal (#PCDATA|a)*>\n"
4487          "<!ELEMENT a EMPTY>\n"
4488          "<!ATTLIST animal xml:space (default|preserve) 'preserve'>",
4489          NULL, NULL};
4490   const XML_Char *expected = XCS("This is a \n      \n\nyellow tiger");
4491 
4492   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
4493   XML_SetUserData(g_parser, &dtd_data);
4494   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4495   /* An attribute list handler provokes a different code path */
4496   XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
4497   run_ext_character_check(text, &dtd_data, expected);
4498 }
4499 END_TEST
4500 
4501 /* Slightly bizarrely, the library seems to silently ignore entity
4502  * definitions for predefined entities, even when they are wrong.  The
4503  * language of the XML 1.0 spec is somewhat unhelpful as to what ought
4504  * to happen, so this is currently treated as acceptable.
4505  */
START_TEST(test_predefined_entity_redefinition)4506 START_TEST(test_predefined_entity_redefinition) {
4507   const char *text = "<!DOCTYPE doc [\n"
4508                      "<!ENTITY apos 'foo'>\n"
4509                      "]>\n"
4510                      "<doc>&apos;</doc>";
4511   run_character_check(text, XCS("'"));
4512 }
4513 END_TEST
4514 
4515 /* Test that the parser stops processing the DTD after an unresolved
4516  * parameter entity is encountered.
4517  */
START_TEST(test_dtd_stop_processing)4518 START_TEST(test_dtd_stop_processing) {
4519   const char *text = "<!DOCTYPE doc [\n"
4520                      "%foo;\n"
4521                      "<!ENTITY bar 'bas'>\n"
4522                      "]><doc/>";
4523 
4524   XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
4525   dummy_handler_flags = 0;
4526   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4527       == XML_STATUS_ERROR)
4528     xml_failure(g_parser);
4529   if (dummy_handler_flags != 0)
4530     fail("DTD processing still going after undefined PE");
4531 }
4532 END_TEST
4533 
4534 /* Test public notations with no system ID */
START_TEST(test_public_notation_no_sysid)4535 START_TEST(test_public_notation_no_sysid) {
4536   const char *text = "<!DOCTYPE doc [\n"
4537                      "<!NOTATION note PUBLIC 'foo'>\n"
4538                      "<!ELEMENT doc EMPTY>\n"
4539                      "]>\n<doc/>";
4540 
4541   dummy_handler_flags = 0;
4542   XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
4543   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4544       == XML_STATUS_ERROR)
4545     xml_failure(g_parser);
4546   if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG)
4547     fail("Notation declaration handler not called");
4548 }
4549 END_TEST
4550 
4551 static void XMLCALL
record_element_start_handler(void * userData,const XML_Char * name,const XML_Char ** atts)4552 record_element_start_handler(void *userData, const XML_Char *name,
4553                              const XML_Char **atts) {
4554   UNUSED_P(atts);
4555   CharData_AppendXMLChars((CharData *)userData, name, (int)xcstrlen(name));
4556 }
4557 
START_TEST(test_nested_groups)4558 START_TEST(test_nested_groups) {
4559   const char *text
4560       = "<!DOCTYPE doc [\n"
4561         "<!ELEMENT doc "
4562         /* Sixteen elements per line */
4563         "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,"
4564         "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?"
4565         "))))))))))))))))))))))))))))))))>\n"
4566         "<!ELEMENT e EMPTY>"
4567         "]>\n"
4568         "<doc><e/></doc>";
4569   CharData storage;
4570 
4571   CharData_Init(&storage);
4572   XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4573   XML_SetStartElementHandler(g_parser, record_element_start_handler);
4574   XML_SetUserData(g_parser, &storage);
4575   dummy_handler_flags = 0;
4576   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4577       == XML_STATUS_ERROR)
4578     xml_failure(g_parser);
4579   CharData_CheckXMLChars(&storage, XCS("doce"));
4580   if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
4581     fail("Element handler not fired");
4582 }
4583 END_TEST
4584 
START_TEST(test_group_choice)4585 START_TEST(test_group_choice) {
4586   const char *text = "<!DOCTYPE doc [\n"
4587                      "<!ELEMENT doc (a|b|c)+>\n"
4588                      "<!ELEMENT a EMPTY>\n"
4589                      "<!ELEMENT b (#PCDATA)>\n"
4590                      "<!ELEMENT c ANY>\n"
4591                      "]>\n"
4592                      "<doc>\n"
4593                      "<a/>\n"
4594                      "<b attr='foo'>This is a foo</b>\n"
4595                      "<c></c>\n"
4596                      "</doc>\n";
4597 
4598   XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4599   dummy_handler_flags = 0;
4600   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4601       == XML_STATUS_ERROR)
4602     xml_failure(g_parser);
4603   if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
4604     fail("Element handler flag not raised");
4605 }
4606 END_TEST
4607 
4608 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)4609 external_entity_public(XML_Parser parser, const XML_Char *context,
4610                        const XML_Char *base, const XML_Char *systemId,
4611                        const XML_Char *publicId) {
4612   const char *text1 = (const char *)XML_GetUserData(parser);
4613   const char *text2 = "<!ATTLIST doc a CDATA 'value'>";
4614   const char *text = NULL;
4615   XML_Parser ext_parser;
4616   int parse_res;
4617 
4618   UNUSED_P(base);
4619   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4620   if (ext_parser == NULL)
4621     return XML_STATUS_ERROR;
4622   if (systemId != NULL && ! xcstrcmp(systemId, XCS("http://example.org/"))) {
4623     text = text1;
4624   } else if (publicId != NULL && ! xcstrcmp(publicId, XCS("foo"))) {
4625     text = text2;
4626   } else
4627     fail("Unexpected parameters to external entity parser");
4628   assert(text != NULL);
4629   parse_res
4630       = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
4631   XML_ParserFree(ext_parser);
4632   return parse_res;
4633 }
4634 
START_TEST(test_standalone_parameter_entity)4635 START_TEST(test_standalone_parameter_entity) {
4636   const char *text = "<?xml version='1.0' standalone='yes'?>\n"
4637                      "<!DOCTYPE doc SYSTEM 'http://example.org/' [\n"
4638                      "<!ENTITY % entity '<!ELEMENT doc (#PCDATA)>'>\n"
4639                      "%entity;\n"
4640                      "]>\n"
4641                      "<doc></doc>";
4642   char dtd_data[] = "<!ENTITY % e1 'foo'>\n";
4643 
4644   XML_SetUserData(g_parser, dtd_data);
4645   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4646   XML_SetExternalEntityRefHandler(g_parser, external_entity_public);
4647   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4648       == XML_STATUS_ERROR)
4649     xml_failure(g_parser);
4650 }
4651 END_TEST
4652 
4653 /* Test skipping of parameter entity in an external DTD */
4654 /* Derived from ibm/invalid/P69/ibm69i01.xml */
START_TEST(test_skipped_parameter_entity)4655 START_TEST(test_skipped_parameter_entity) {
4656   const char *text = "<?xml version='1.0'?>\n"
4657                      "<!DOCTYPE root SYSTEM 'http://example.org/dtd.ent' [\n"
4658                      "<!ELEMENT root (#PCDATA|a)* >\n"
4659                      "]>\n"
4660                      "<root></root>";
4661   ExtTest dtd_data = {"%pe2;", NULL, NULL};
4662 
4663   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
4664   XML_SetUserData(g_parser, &dtd_data);
4665   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4666   XML_SetSkippedEntityHandler(g_parser, dummy_skip_handler);
4667   dummy_handler_flags = 0;
4668   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4669       == XML_STATUS_ERROR)
4670     xml_failure(g_parser);
4671   if (dummy_handler_flags != DUMMY_SKIP_HANDLER_FLAG)
4672     fail("Skip handler not executed");
4673 }
4674 END_TEST
4675 
4676 /* Test recursive parameter entity definition rejected in external DTD */
START_TEST(test_recursive_external_parameter_entity)4677 START_TEST(test_recursive_external_parameter_entity) {
4678   const char *text = "<?xml version='1.0'?>\n"
4679                      "<!DOCTYPE root SYSTEM 'http://example.org/dtd.ent' [\n"
4680                      "<!ELEMENT root (#PCDATA|a)* >\n"
4681                      "]>\n"
4682                      "<root></root>";
4683   ExtFaults dtd_data = {"<!ENTITY % pe2 '&#37;pe2;'>\n%pe2;",
4684                         "Recursive external parameter entity not faulted", NULL,
4685                         XML_ERROR_RECURSIVE_ENTITY_REF};
4686 
4687   XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
4688   XML_SetUserData(g_parser, &dtd_data);
4689   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4690   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
4691                  "Recursive external parameter not spotted");
4692 }
4693 END_TEST
4694 
4695 /* Test undefined parameter entity in external entity handler */
4696 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)4697 external_entity_devaluer(XML_Parser parser, const XML_Char *context,
4698                          const XML_Char *base, const XML_Char *systemId,
4699                          const XML_Char *publicId) {
4700   const char *text = "<!ELEMENT doc EMPTY>\n"
4701                      "<!ENTITY % e1 SYSTEM 'bar'>\n"
4702                      "%e1;\n";
4703   XML_Parser ext_parser;
4704   intptr_t clear_handler = (intptr_t)XML_GetUserData(parser);
4705 
4706   UNUSED_P(base);
4707   UNUSED_P(publicId);
4708   if (systemId == NULL || ! xcstrcmp(systemId, XCS("bar")))
4709     return XML_STATUS_OK;
4710   if (xcstrcmp(systemId, XCS("foo")))
4711     fail("Unexpected system ID");
4712   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4713   if (ext_parser == NULL)
4714     fail("Could note create external entity parser");
4715   if (clear_handler)
4716     XML_SetExternalEntityRefHandler(ext_parser, NULL);
4717   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
4718       == XML_STATUS_ERROR)
4719     xml_failure(ext_parser);
4720 
4721   XML_ParserFree(ext_parser);
4722   return XML_STATUS_OK;
4723 }
4724 
START_TEST(test_undefined_ext_entity_in_external_dtd)4725 START_TEST(test_undefined_ext_entity_in_external_dtd) {
4726   const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
4727                      "<doc></doc>\n";
4728 
4729   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4730   XML_SetExternalEntityRefHandler(g_parser, external_entity_devaluer);
4731   XML_SetUserData(g_parser, (void *)(intptr_t)XML_FALSE);
4732   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4733       == XML_STATUS_ERROR)
4734     xml_failure(g_parser);
4735 
4736   /* Now repeat without the external entity ref handler invoking
4737    * another copy of itself.
4738    */
4739   XML_ParserReset(g_parser, NULL);
4740   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4741   XML_SetExternalEntityRefHandler(g_parser, external_entity_devaluer);
4742   XML_SetUserData(g_parser, (void *)(intptr_t)XML_TRUE);
4743   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4744       == XML_STATUS_ERROR)
4745     xml_failure(g_parser);
4746 }
4747 END_TEST
4748 
4749 static void XMLCALL
aborting_xdecl_handler(void * userData,const XML_Char * version,const XML_Char * encoding,int standalone)4750 aborting_xdecl_handler(void *userData, const XML_Char *version,
4751                        const XML_Char *encoding, int standalone) {
4752   UNUSED_P(userData);
4753   UNUSED_P(version);
4754   UNUSED_P(encoding);
4755   UNUSED_P(standalone);
4756   XML_StopParser(g_parser, resumable);
4757   XML_SetXmlDeclHandler(g_parser, NULL);
4758 }
4759 
4760 /* Test suspending the parse on receiving an XML declaration works */
START_TEST(test_suspend_xdecl)4761 START_TEST(test_suspend_xdecl) {
4762   const char *text = long_character_data_text;
4763 
4764   XML_SetXmlDeclHandler(g_parser, aborting_xdecl_handler);
4765   resumable = XML_TRUE;
4766   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4767       != XML_STATUS_SUSPENDED)
4768     xml_failure(g_parser);
4769   if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE)
4770     xml_failure(g_parser);
4771   /* Attempt to start a new parse while suspended */
4772   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
4773       != XML_STATUS_ERROR)
4774     fail("Attempt to parse while suspended not faulted");
4775   if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED)
4776     fail("Suspended parse not faulted with correct error");
4777 }
4778 END_TEST
4779 
4780 /* Test aborting the parse in an epilog works */
4781 static void XMLCALL
selective_aborting_default_handler(void * userData,const XML_Char * s,int len)4782 selective_aborting_default_handler(void *userData, const XML_Char *s, int len) {
4783   const XML_Char *match = (const XML_Char *)userData;
4784 
4785   if (match == NULL
4786       || (xcstrlen(match) == (unsigned)len && ! xcstrncmp(match, s, len))) {
4787     XML_StopParser(g_parser, resumable);
4788     XML_SetDefaultHandler(g_parser, NULL);
4789   }
4790 }
4791 
START_TEST(test_abort_epilog)4792 START_TEST(test_abort_epilog) {
4793   const char *text = "<doc></doc>\n\r\n";
4794   XML_Char match[] = XCS("\r");
4795 
4796   XML_SetDefaultHandler(g_parser, selective_aborting_default_handler);
4797   XML_SetUserData(g_parser, match);
4798   resumable = XML_FALSE;
4799   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4800       != XML_STATUS_ERROR)
4801     fail("Abort not triggered");
4802   if (XML_GetErrorCode(g_parser) != XML_ERROR_ABORTED)
4803     xml_failure(g_parser);
4804 }
4805 END_TEST
4806 
4807 /* Test a different code path for abort in the epilog */
START_TEST(test_abort_epilog_2)4808 START_TEST(test_abort_epilog_2) {
4809   const char *text = "<doc></doc>\n";
4810   XML_Char match[] = XCS("\n");
4811 
4812   XML_SetDefaultHandler(g_parser, selective_aborting_default_handler);
4813   XML_SetUserData(g_parser, match);
4814   resumable = XML_FALSE;
4815   expect_failure(text, XML_ERROR_ABORTED, "Abort not triggered");
4816 }
4817 END_TEST
4818 
4819 /* Test suspension from the epilog */
START_TEST(test_suspend_epilog)4820 START_TEST(test_suspend_epilog) {
4821   const char *text = "<doc></doc>\n";
4822   XML_Char match[] = XCS("\n");
4823 
4824   XML_SetDefaultHandler(g_parser, selective_aborting_default_handler);
4825   XML_SetUserData(g_parser, match);
4826   resumable = XML_TRUE;
4827   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4828       != XML_STATUS_SUSPENDED)
4829     xml_failure(g_parser);
4830 }
4831 END_TEST
4832 
4833 static void XMLCALL
suspending_end_handler(void * userData,const XML_Char * s)4834 suspending_end_handler(void *userData, const XML_Char *s) {
4835   UNUSED_P(s);
4836   XML_StopParser((XML_Parser)userData, 1);
4837 }
4838 
START_TEST(test_suspend_in_sole_empty_tag)4839 START_TEST(test_suspend_in_sole_empty_tag) {
4840   const char *text = "<doc/>";
4841   enum XML_Status rc;
4842 
4843   XML_SetEndElementHandler(g_parser, suspending_end_handler);
4844   XML_SetUserData(g_parser, g_parser);
4845   rc = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE);
4846   if (rc == XML_STATUS_ERROR)
4847     xml_failure(g_parser);
4848   else if (rc != XML_STATUS_SUSPENDED)
4849     fail("Suspend not triggered");
4850   rc = XML_ResumeParser(g_parser);
4851   if (rc == XML_STATUS_ERROR)
4852     xml_failure(g_parser);
4853   else if (rc != XML_STATUS_OK)
4854     fail("Resume failed");
4855 }
4856 END_TEST
4857 
START_TEST(test_unfinished_epilog)4858 START_TEST(test_unfinished_epilog) {
4859   const char *text = "<doc></doc><";
4860 
4861   expect_failure(text, XML_ERROR_UNCLOSED_TOKEN,
4862                  "Incomplete epilog entry not faulted");
4863 }
4864 END_TEST
4865 
START_TEST(test_partial_char_in_epilog)4866 START_TEST(test_partial_char_in_epilog) {
4867   const char *text = "<doc></doc>\xe2\x82";
4868 
4869   /* First check that no fault is raised if the parse is not finished */
4870   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
4871       == XML_STATUS_ERROR)
4872     xml_failure(g_parser);
4873   /* Now check that it is faulted once we finish */
4874   if (XML_ParseBuffer(g_parser, 0, XML_TRUE) != XML_STATUS_ERROR)
4875     fail("Partial character in epilog not faulted");
4876   if (XML_GetErrorCode(g_parser) != XML_ERROR_PARTIAL_CHAR)
4877     xml_failure(g_parser);
4878 }
4879 END_TEST
4880 
START_TEST(test_hash_collision)4881 START_TEST(test_hash_collision) {
4882   /* For full coverage of the lookup routine, we need to ensure a
4883    * hash collision even though we can only tell that we have one
4884    * through breakpoint debugging or coverage statistics.  The
4885    * following will cause a hash collision on machines with a 64-bit
4886    * long type; others will have to experiment.  The full coverage
4887    * tests invoked from qa.sh usually provide a hash collision, but
4888    * not always.  This is an attempt to provide insurance.
4889    */
4890 #define COLLIDING_HASH_SALT (unsigned long)_SIP_ULL(0xffffffffU, 0xff99fc90U)
4891   const char *text
4892       = "<doc>\n"
4893         "<a1/><a2/><a3/><a4/><a5/><a6/><a7/><a8/>\n"
4894         "<b1></b1><b2 attr='foo'>This is a foo</b2><b3></b3><b4></b4>\n"
4895         "<b5></b5><b6></b6><b7></b7><b8></b8>\n"
4896         "<c1/><c2/><c3/><c4/><c5/><c6/><c7/><c8/>\n"
4897         "<d1/><d2/><d3/><d4/><d5/><d6/><d7/>\n"
4898         "<d8>This triggers the table growth and collides with b2</d8>\n"
4899         "</doc>\n";
4900 
4901   XML_SetHashSalt(g_parser, COLLIDING_HASH_SALT);
4902   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4903       == XML_STATUS_ERROR)
4904     xml_failure(g_parser);
4905 }
4906 END_TEST
4907 #undef COLLIDING_HASH_SALT
4908 
4909 /* Test resuming a parse suspended in entity substitution */
4910 static void XMLCALL
start_element_suspender(void * userData,const XML_Char * name,const XML_Char ** atts)4911 start_element_suspender(void *userData, const XML_Char *name,
4912                         const XML_Char **atts) {
4913   UNUSED_P(userData);
4914   UNUSED_P(atts);
4915   if (! xcstrcmp(name, XCS("suspend")))
4916     XML_StopParser(g_parser, XML_TRUE);
4917   if (! xcstrcmp(name, XCS("abort")))
4918     XML_StopParser(g_parser, XML_FALSE);
4919 }
4920 
START_TEST(test_suspend_resume_internal_entity)4921 START_TEST(test_suspend_resume_internal_entity) {
4922   const char *text
4923       = "<!DOCTYPE doc [\n"
4924         "<!ENTITY foo '<suspend>Hi<suspend>Ho</suspend></suspend>'>\n"
4925         "]>\n"
4926         "<doc>&foo;</doc>\n";
4927   const XML_Char *expected1 = XCS("Hi");
4928   const XML_Char *expected2 = XCS("HiHo");
4929   CharData storage;
4930 
4931   CharData_Init(&storage);
4932   XML_SetStartElementHandler(g_parser, start_element_suspender);
4933   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
4934   XML_SetUserData(g_parser, &storage);
4935   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
4936       != XML_STATUS_SUSPENDED)
4937     xml_failure(g_parser);
4938   CharData_CheckXMLChars(&storage, XCS(""));
4939   if (XML_ResumeParser(g_parser) != XML_STATUS_SUSPENDED)
4940     xml_failure(g_parser);
4941   CharData_CheckXMLChars(&storage, expected1);
4942   if (XML_ResumeParser(g_parser) != XML_STATUS_OK)
4943     xml_failure(g_parser);
4944   CharData_CheckXMLChars(&storage, expected2);
4945 }
4946 END_TEST
4947 
4948 void
suspending_comment_handler(void * userData,const XML_Char * data)4949 suspending_comment_handler(void *userData, const XML_Char *data) {
4950   UNUSED_P(data);
4951   XML_Parser parser = (XML_Parser)userData;
4952   XML_StopParser(parser, XML_TRUE);
4953 }
4954 
START_TEST(test_suspend_resume_internal_entity_issue_629)4955 START_TEST(test_suspend_resume_internal_entity_issue_629) {
4956   const char *const text
4957       = "<!DOCTYPE a [<!ENTITY e '<!--COMMENT-->a'>]><a>&e;<b>\n"
4958         "<"
4959         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4960         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4961         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4962         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4963         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4964         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4965         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4966         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4967         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4968         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4969         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4970         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4971         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4972         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4973         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4974         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4975         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4976         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4977         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4978         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4979         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4980         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4981         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4982         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4983         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4984         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4985         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4986         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4987         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4988         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4989         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4990         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4991         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4992         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4993         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4994         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4995         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4996         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4997         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4998         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4999         "/>"
5000         "</b></a>";
5001   const size_t firstChunkSizeBytes = 54;
5002 
5003   XML_Parser parser = XML_ParserCreate(NULL);
5004   XML_SetUserData(parser, parser);
5005   XML_SetCommentHandler(parser, suspending_comment_handler);
5006 
5007   if (XML_Parse(parser, text, (int)firstChunkSizeBytes, XML_FALSE)
5008       != XML_STATUS_SUSPENDED)
5009     xml_failure(parser);
5010   if (XML_ResumeParser(parser) != XML_STATUS_OK)
5011     xml_failure(parser);
5012   if (XML_Parse(parser, text + firstChunkSizeBytes,
5013                 (int)(strlen(text) - firstChunkSizeBytes), XML_TRUE)
5014       != XML_STATUS_OK)
5015     xml_failure(parser);
5016   XML_ParserFree(parser);
5017 }
5018 END_TEST
5019 
5020 /* Test syntax error is caught at parse resumption */
START_TEST(test_resume_entity_with_syntax_error)5021 START_TEST(test_resume_entity_with_syntax_error) {
5022   const char *text = "<!DOCTYPE doc [\n"
5023                      "<!ENTITY foo '<suspend>Hi</wombat>'>\n"
5024                      "]>\n"
5025                      "<doc>&foo;</doc>\n";
5026 
5027   XML_SetStartElementHandler(g_parser, start_element_suspender);
5028   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
5029       != XML_STATUS_SUSPENDED)
5030     xml_failure(g_parser);
5031   if (XML_ResumeParser(g_parser) != XML_STATUS_ERROR)
5032     fail("Syntax error in entity not faulted");
5033   if (XML_GetErrorCode(g_parser) != XML_ERROR_TAG_MISMATCH)
5034     xml_failure(g_parser);
5035 }
5036 END_TEST
5037 
5038 /* Test suspending and resuming in a parameter entity substitution */
5039 static void XMLCALL
element_decl_suspender(void * userData,const XML_Char * name,XML_Content * model)5040 element_decl_suspender(void *userData, const XML_Char *name,
5041                        XML_Content *model) {
5042   UNUSED_P(userData);
5043   UNUSED_P(name);
5044   XML_StopParser(g_parser, XML_TRUE);
5045   XML_FreeContentModel(g_parser, model);
5046 }
5047 
START_TEST(test_suspend_resume_parameter_entity)5048 START_TEST(test_suspend_resume_parameter_entity) {
5049   const char *text = "<!DOCTYPE doc [\n"
5050                      "<!ENTITY % foo '<!ELEMENT doc (#PCDATA)*>'>\n"
5051                      "%foo;\n"
5052                      "]>\n"
5053                      "<doc>Hello, world</doc>";
5054   const XML_Char *expected = XCS("Hello, world");
5055   CharData storage;
5056 
5057   CharData_Init(&storage);
5058   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5059   XML_SetElementDeclHandler(g_parser, element_decl_suspender);
5060   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
5061   XML_SetUserData(g_parser, &storage);
5062   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
5063       != XML_STATUS_SUSPENDED)
5064     xml_failure(g_parser);
5065   CharData_CheckXMLChars(&storage, XCS(""));
5066   if (XML_ResumeParser(g_parser) != XML_STATUS_OK)
5067     xml_failure(g_parser);
5068   CharData_CheckXMLChars(&storage, expected);
5069 }
5070 END_TEST
5071 
5072 /* Test attempting to use parser after an error is faulted */
START_TEST(test_restart_on_error)5073 START_TEST(test_restart_on_error) {
5074   const char *text = "<$doc><doc></doc>";
5075 
5076   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
5077       != XML_STATUS_ERROR)
5078     fail("Invalid tag name not faulted");
5079   if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
5080     xml_failure(g_parser);
5081   if (XML_Parse(g_parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR)
5082     fail("Restarting invalid parse not faulted");
5083   if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
5084     xml_failure(g_parser);
5085 }
5086 END_TEST
5087 
5088 /* Test that angle brackets in an attribute default value are faulted */
START_TEST(test_reject_lt_in_attribute_value)5089 START_TEST(test_reject_lt_in_attribute_value) {
5090   const char *text = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '<bar>'>]>\n"
5091                      "<doc></doc>";
5092 
5093   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5094                  "Bad attribute default not faulted");
5095 }
5096 END_TEST
5097 
START_TEST(test_reject_unfinished_param_in_att_value)5098 START_TEST(test_reject_unfinished_param_in_att_value) {
5099   const char *text = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '&foo'>]>\n"
5100                      "<doc></doc>";
5101 
5102   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5103                  "Bad attribute default not faulted");
5104 }
5105 END_TEST
5106 
START_TEST(test_trailing_cr_in_att_value)5107 START_TEST(test_trailing_cr_in_att_value) {
5108   const char *text = "<doc a='value\r'/>";
5109 
5110   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5111       == XML_STATUS_ERROR)
5112     xml_failure(g_parser);
5113 }
5114 END_TEST
5115 
5116 /* Try parsing a general entity within a parameter entity in a
5117  * standalone internal DTD.  Covers a corner case in the parser.
5118  */
START_TEST(test_standalone_internal_entity)5119 START_TEST(test_standalone_internal_entity) {
5120   const char *text = "<?xml version='1.0' standalone='yes' ?>\n"
5121                      "<!DOCTYPE doc [\n"
5122                      "  <!ELEMENT doc (#PCDATA)>\n"
5123                      "  <!ENTITY % pe '<!ATTLIST doc att2 CDATA \"&ge;\">'>\n"
5124                      "  <!ENTITY ge 'AttDefaultValue'>\n"
5125                      "  %pe;\n"
5126                      "]>\n"
5127                      "<doc att2='any'/>";
5128 
5129   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5130   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5131       == XML_STATUS_ERROR)
5132     xml_failure(g_parser);
5133 }
5134 END_TEST
5135 
5136 /* Test that a reference to an unknown external entity is skipped */
START_TEST(test_skipped_external_entity)5137 START_TEST(test_skipped_external_entity) {
5138   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
5139                      "<doc></doc>\n";
5140   ExtTest test_data = {"<!ELEMENT doc EMPTY>\n"
5141                        "<!ENTITY % e2 '%e1;'>\n",
5142                        NULL, NULL};
5143 
5144   XML_SetUserData(g_parser, &test_data);
5145   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5146   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
5147   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5148       == XML_STATUS_ERROR)
5149     xml_failure(g_parser);
5150 }
5151 END_TEST
5152 
5153 /* Test a different form of unknown external entity */
5154 typedef struct ext_hdlr_data {
5155   const char *parse_text;
5156   XML_ExternalEntityRefHandler handler;
5157 } ExtHdlrData;
5158 
5159 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)5160 external_entity_oneshot_loader(XML_Parser parser, const XML_Char *context,
5161                                const XML_Char *base, const XML_Char *systemId,
5162                                const XML_Char *publicId) {
5163   ExtHdlrData *test_data = (ExtHdlrData *)XML_GetUserData(parser);
5164   XML_Parser ext_parser;
5165 
5166   UNUSED_P(base);
5167   UNUSED_P(systemId);
5168   UNUSED_P(publicId);
5169   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
5170   if (ext_parser == NULL)
5171     fail("Could not create external entity parser.");
5172   /* Use the requested entity parser for further externals */
5173   XML_SetExternalEntityRefHandler(ext_parser, test_data->handler);
5174   if (_XML_Parse_SINGLE_BYTES(ext_parser, test_data->parse_text,
5175                               (int)strlen(test_data->parse_text), XML_TRUE)
5176       == XML_STATUS_ERROR) {
5177     xml_failure(ext_parser);
5178   }
5179 
5180   XML_ParserFree(ext_parser);
5181   return XML_STATUS_OK;
5182 }
5183 
START_TEST(test_skipped_null_loaded_ext_entity)5184 START_TEST(test_skipped_null_loaded_ext_entity) {
5185   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n"
5186                      "<doc />";
5187   ExtHdlrData test_data
5188       = {"<!ENTITY % pe1 SYSTEM 'http://example.org/two.ent'>\n"
5189          "<!ENTITY % pe2 '%pe1;'>\n"
5190          "%pe2;\n",
5191          external_entity_null_loader};
5192 
5193   XML_SetUserData(g_parser, &test_data);
5194   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5195   XML_SetExternalEntityRefHandler(g_parser, external_entity_oneshot_loader);
5196   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5197       == XML_STATUS_ERROR)
5198     xml_failure(g_parser);
5199 }
5200 END_TEST
5201 
START_TEST(test_skipped_unloaded_ext_entity)5202 START_TEST(test_skipped_unloaded_ext_entity) {
5203   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n"
5204                      "<doc />";
5205   ExtHdlrData test_data
5206       = {"<!ENTITY % pe1 SYSTEM 'http://example.org/two.ent'>\n"
5207          "<!ENTITY % pe2 '%pe1;'>\n"
5208          "%pe2;\n",
5209          NULL};
5210 
5211   XML_SetUserData(g_parser, &test_data);
5212   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5213   XML_SetExternalEntityRefHandler(g_parser, external_entity_oneshot_loader);
5214   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5215       == XML_STATUS_ERROR)
5216     xml_failure(g_parser);
5217 }
5218 END_TEST
5219 
5220 /* Test that a parameter entity value ending with a carriage return
5221  * has it translated internally into a newline.
5222  */
START_TEST(test_param_entity_with_trailing_cr)5223 START_TEST(test_param_entity_with_trailing_cr) {
5224 #define PARAM_ENTITY_NAME "pe"
5225 #define PARAM_ENTITY_CORE_VALUE "<!ATTLIST doc att CDATA \"default\">"
5226   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
5227                      "<doc/>";
5228   ExtTest test_data
5229       = {"<!ENTITY % " PARAM_ENTITY_NAME " '" PARAM_ENTITY_CORE_VALUE "\r'>\n"
5230          "%" PARAM_ENTITY_NAME ";\n",
5231          NULL, NULL};
5232 
5233   XML_SetUserData(g_parser, &test_data);
5234   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5235   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
5236   XML_SetEntityDeclHandler(g_parser, param_entity_match_handler);
5237   entity_name_to_match = XCS(PARAM_ENTITY_NAME);
5238   entity_value_to_match = XCS(PARAM_ENTITY_CORE_VALUE) XCS("\n");
5239   entity_match_flag = ENTITY_MATCH_NOT_FOUND;
5240   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5241       == XML_STATUS_ERROR)
5242     xml_failure(g_parser);
5243   if (entity_match_flag == ENTITY_MATCH_FAIL)
5244     fail("Parameter entity CR->NEWLINE conversion failed");
5245   else if (entity_match_flag == ENTITY_MATCH_NOT_FOUND)
5246     fail("Parameter entity not parsed");
5247 }
5248 #undef PARAM_ENTITY_NAME
5249 #undef PARAM_ENTITY_CORE_VALUE
5250 END_TEST
5251 
START_TEST(test_invalid_character_entity)5252 START_TEST(test_invalid_character_entity) {
5253   const char *text = "<!DOCTYPE doc [\n"
5254                      "  <!ENTITY entity '&#x110000;'>\n"
5255                      "]>\n"
5256                      "<doc>&entity;</doc>";
5257 
5258   expect_failure(text, XML_ERROR_BAD_CHAR_REF,
5259                  "Out of range character reference not faulted");
5260 }
5261 END_TEST
5262 
START_TEST(test_invalid_character_entity_2)5263 START_TEST(test_invalid_character_entity_2) {
5264   const char *text = "<!DOCTYPE doc [\n"
5265                      "  <!ENTITY entity '&#xg0;'>\n"
5266                      "]>\n"
5267                      "<doc>&entity;</doc>";
5268 
5269   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5270                  "Out of range character reference not faulted");
5271 }
5272 END_TEST
5273 
START_TEST(test_invalid_character_entity_3)5274 START_TEST(test_invalid_character_entity_3) {
5275   const char text[] =
5276       /* <!DOCTYPE doc [\n */
5277       "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0\n"
5278       /* U+0E04 = KHO KHWAI
5279        * U+0E08 = CHO CHAN */
5280       /* <!ENTITY entity '&\u0e04\u0e08;'>\n */
5281       "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0e\0n\0t\0i\0t\0y\0 "
5282       "\0'\0&\x0e\x04\x0e\x08\0;\0'\0>\0\n"
5283       /* ]>\n */
5284       "\0]\0>\0\n"
5285       /* <doc>&entity;</doc> */
5286       "\0<\0d\0o\0c\0>\0&\0e\0n\0t\0i\0t\0y\0;\0<\0/\0d\0o\0c\0>";
5287 
5288   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5289       != XML_STATUS_ERROR)
5290     fail("Invalid start of entity name not faulted");
5291   if (XML_GetErrorCode(g_parser) != XML_ERROR_UNDEFINED_ENTITY)
5292     xml_failure(g_parser);
5293 }
5294 END_TEST
5295 
START_TEST(test_invalid_character_entity_4)5296 START_TEST(test_invalid_character_entity_4) {
5297   const char *text = "<!DOCTYPE doc [\n"
5298                      "  <!ENTITY entity '&#1114112;'>\n" /* = &#x110000 */
5299                      "]>\n"
5300                      "<doc>&entity;</doc>";
5301 
5302   expect_failure(text, XML_ERROR_BAD_CHAR_REF,
5303                  "Out of range character reference not faulted");
5304 }
5305 END_TEST
5306 
5307 /* Test that processing instructions are picked up by a default handler */
START_TEST(test_pi_handled_in_default)5308 START_TEST(test_pi_handled_in_default) {
5309   const char *text = "<?test processing instruction?>\n<doc/>";
5310   const XML_Char *expected = XCS("<?test processing instruction?>\n<doc/>");
5311   CharData storage;
5312 
5313   CharData_Init(&storage);
5314   XML_SetDefaultHandler(g_parser, accumulate_characters);
5315   XML_SetUserData(g_parser, &storage);
5316   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5317       == XML_STATUS_ERROR)
5318     xml_failure(g_parser);
5319   CharData_CheckXMLChars(&storage, expected);
5320 }
5321 END_TEST
5322 
5323 /* Test that comments are picked up by a default handler */
START_TEST(test_comment_handled_in_default)5324 START_TEST(test_comment_handled_in_default) {
5325   const char *text = "<!-- This is a comment -->\n<doc/>";
5326   const XML_Char *expected = XCS("<!-- This is a comment -->\n<doc/>");
5327   CharData storage;
5328 
5329   CharData_Init(&storage);
5330   XML_SetDefaultHandler(g_parser, accumulate_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 
5339 /* Test PIs that look almost but not quite like XML declarations */
5340 static void XMLCALL
accumulate_pi_characters(void * userData,const XML_Char * target,const XML_Char * data)5341 accumulate_pi_characters(void *userData, const XML_Char *target,
5342                          const XML_Char *data) {
5343   CharData *storage = (CharData *)userData;
5344 
5345   CharData_AppendXMLChars(storage, target, -1);
5346   CharData_AppendXMLChars(storage, XCS(": "), 2);
5347   CharData_AppendXMLChars(storage, data, -1);
5348   CharData_AppendXMLChars(storage, XCS("\n"), 1);
5349 }
5350 
START_TEST(test_pi_yml)5351 START_TEST(test_pi_yml) {
5352   const char *text = "<?yml something like data?><doc/>";
5353   const XML_Char *expected = XCS("yml: something like data\n");
5354   CharData storage;
5355 
5356   CharData_Init(&storage);
5357   XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5358   XML_SetUserData(g_parser, &storage);
5359   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5360       == XML_STATUS_ERROR)
5361     xml_failure(g_parser);
5362   CharData_CheckXMLChars(&storage, expected);
5363 }
5364 END_TEST
5365 
START_TEST(test_pi_xnl)5366 START_TEST(test_pi_xnl) {
5367   const char *text = "<?xnl nothing like data?><doc/>";
5368   const XML_Char *expected = XCS("xnl: nothing like data\n");
5369   CharData storage;
5370 
5371   CharData_Init(&storage);
5372   XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5373   XML_SetUserData(g_parser, &storage);
5374   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5375       == XML_STATUS_ERROR)
5376     xml_failure(g_parser);
5377   CharData_CheckXMLChars(&storage, expected);
5378 }
5379 END_TEST
5380 
START_TEST(test_pi_xmm)5381 START_TEST(test_pi_xmm) {
5382   const char *text = "<?xmm everything like data?><doc/>";
5383   const XML_Char *expected = XCS("xmm: everything like data\n");
5384   CharData storage;
5385 
5386   CharData_Init(&storage);
5387   XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5388   XML_SetUserData(g_parser, &storage);
5389   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5390       == XML_STATUS_ERROR)
5391     xml_failure(g_parser);
5392   CharData_CheckXMLChars(&storage, expected);
5393 }
5394 END_TEST
5395 
START_TEST(test_utf16_pi)5396 START_TEST(test_utf16_pi) {
5397   const char text[] =
5398       /* <?{KHO KHWAI}{CHO CHAN}?>
5399        * where {KHO KHWAI} = U+0E04
5400        * and   {CHO CHAN}  = U+0E08
5401        */
5402       "<\0?\0\x04\x0e\x08\x0e?\0>\0"
5403       /* <q/> */
5404       "<\0q\0/\0>\0";
5405 #ifdef XML_UNICODE
5406   const XML_Char *expected = XCS("\x0e04\x0e08: \n");
5407 #else
5408   const XML_Char *expected = XCS("\xe0\xb8\x84\xe0\xb8\x88: \n");
5409 #endif
5410   CharData storage;
5411 
5412   CharData_Init(&storage);
5413   XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5414   XML_SetUserData(g_parser, &storage);
5415   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5416       == XML_STATUS_ERROR)
5417     xml_failure(g_parser);
5418   CharData_CheckXMLChars(&storage, expected);
5419 }
5420 END_TEST
5421 
START_TEST(test_utf16_be_pi)5422 START_TEST(test_utf16_be_pi) {
5423   const char text[] =
5424       /* <?{KHO KHWAI}{CHO CHAN}?>
5425        * where {KHO KHWAI} = U+0E04
5426        * and   {CHO CHAN}  = U+0E08
5427        */
5428       "\0<\0?\x0e\x04\x0e\x08\0?\0>"
5429       /* <q/> */
5430       "\0<\0q\0/\0>";
5431 #ifdef XML_UNICODE
5432   const XML_Char *expected = XCS("\x0e04\x0e08: \n");
5433 #else
5434   const XML_Char *expected = XCS("\xe0\xb8\x84\xe0\xb8\x88: \n");
5435 #endif
5436   CharData storage;
5437 
5438   CharData_Init(&storage);
5439   XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
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 
5448 /* Test that comments can be picked up and translated */
5449 static void XMLCALL
accumulate_comment(void * userData,const XML_Char * data)5450 accumulate_comment(void *userData, const XML_Char *data) {
5451   CharData *storage = (CharData *)userData;
5452 
5453   CharData_AppendXMLChars(storage, data, -1);
5454 }
5455 
START_TEST(test_utf16_be_comment)5456 START_TEST(test_utf16_be_comment) {
5457   const char text[] =
5458       /* <!-- Comment A --> */
5459       "\0<\0!\0-\0-\0 \0C\0o\0m\0m\0e\0n\0t\0 \0A\0 \0-\0-\0>\0\n"
5460       /* <doc/> */
5461       "\0<\0d\0o\0c\0/\0>";
5462   const XML_Char *expected = XCS(" Comment A ");
5463   CharData storage;
5464 
5465   CharData_Init(&storage);
5466   XML_SetCommentHandler(g_parser, accumulate_comment);
5467   XML_SetUserData(g_parser, &storage);
5468   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5469       == XML_STATUS_ERROR)
5470     xml_failure(g_parser);
5471   CharData_CheckXMLChars(&storage, expected);
5472 }
5473 END_TEST
5474 
START_TEST(test_utf16_le_comment)5475 START_TEST(test_utf16_le_comment) {
5476   const char text[] =
5477       /* <!-- Comment B --> */
5478       "<\0!\0-\0-\0 \0C\0o\0m\0m\0e\0n\0t\0 \0B\0 \0-\0-\0>\0\n\0"
5479       /* <doc/> */
5480       "<\0d\0o\0c\0/\0>\0";
5481   const XML_Char *expected = XCS(" Comment B ");
5482   CharData storage;
5483 
5484   CharData_Init(&storage);
5485   XML_SetCommentHandler(g_parser, accumulate_comment);
5486   XML_SetUserData(g_parser, &storage);
5487   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5488       == XML_STATUS_ERROR)
5489     xml_failure(g_parser);
5490   CharData_CheckXMLChars(&storage, expected);
5491 }
5492 END_TEST
5493 
5494 /* Test that the unknown encoding handler with map entries that expect
5495  * conversion but no conversion function is faulted
5496  */
5497 static int XMLCALL
failing_converter(void * data,const char * s)5498 failing_converter(void *data, const char *s) {
5499   UNUSED_P(data);
5500   UNUSED_P(s);
5501   /* Always claim to have failed */
5502   return -1;
5503 }
5504 
5505 static int XMLCALL
prefix_converter(void * data,const char * s)5506 prefix_converter(void *data, const char *s) {
5507   UNUSED_P(data);
5508   /* If the first byte is 0xff, raise an error */
5509   if (s[0] == (char)-1)
5510     return -1;
5511   /* Just add the low bits of the first byte to the second */
5512   return (s[1] + (s[0] & 0x7f)) & 0x01ff;
5513 }
5514 
5515 static int XMLCALL
MiscEncodingHandler(void * data,const XML_Char * encoding,XML_Encoding * info)5516 MiscEncodingHandler(void *data, const XML_Char *encoding, XML_Encoding *info) {
5517   int i;
5518   int high_map = -2; /* Assume a 2-byte sequence */
5519 
5520   if (! xcstrcmp(encoding, XCS("invalid-9"))
5521       || ! xcstrcmp(encoding, XCS("ascii-like"))
5522       || ! xcstrcmp(encoding, XCS("invalid-len"))
5523       || ! xcstrcmp(encoding, XCS("invalid-a"))
5524       || ! xcstrcmp(encoding, XCS("invalid-surrogate"))
5525       || ! xcstrcmp(encoding, XCS("invalid-high")))
5526     high_map = -1;
5527 
5528   for (i = 0; i < 128; ++i)
5529     info->map[i] = i;
5530   for (; i < 256; ++i)
5531     info->map[i] = high_map;
5532 
5533   /* If required, put an invalid value in the ASCII entries */
5534   if (! xcstrcmp(encoding, XCS("invalid-9")))
5535     info->map[9] = 5;
5536   /* If required, have a top-bit set character starts a 5-byte sequence */
5537   if (! xcstrcmp(encoding, XCS("invalid-len")))
5538     info->map[0x81] = -5;
5539   /* If required, make a top-bit set character a valid ASCII character */
5540   if (! xcstrcmp(encoding, XCS("invalid-a")))
5541     info->map[0x82] = 'a';
5542   /* If required, give a top-bit set character a forbidden value,
5543    * what would otherwise be the first of a surrogate pair.
5544    */
5545   if (! xcstrcmp(encoding, XCS("invalid-surrogate")))
5546     info->map[0x83] = 0xd801;
5547   /* If required, give a top-bit set character too high a value */
5548   if (! xcstrcmp(encoding, XCS("invalid-high")))
5549     info->map[0x84] = 0x010101;
5550 
5551   info->data = data;
5552   info->release = NULL;
5553   if (! xcstrcmp(encoding, XCS("failing-conv")))
5554     info->convert = failing_converter;
5555   else if (! xcstrcmp(encoding, XCS("prefix-conv")))
5556     info->convert = prefix_converter;
5557   else
5558     info->convert = NULL;
5559   return XML_STATUS_OK;
5560 }
5561 
START_TEST(test_missing_encoding_conversion_fn)5562 START_TEST(test_missing_encoding_conversion_fn) {
5563   const char *text = "<?xml version='1.0' encoding='no-conv'?>\n"
5564                      "<doc>\x81</doc>";
5565 
5566   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5567   /* MiscEncodingHandler sets up an encoding with every top-bit-set
5568    * character introducing a two-byte sequence.  For this, it
5569    * requires a convert function.  The above function call doesn't
5570    * pass one through, so when BadEncodingHandler actually gets
5571    * called it should supply an invalid encoding.
5572    */
5573   expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5574                  "Encoding with missing convert() not faulted");
5575 }
5576 END_TEST
5577 
START_TEST(test_failing_encoding_conversion_fn)5578 START_TEST(test_failing_encoding_conversion_fn) {
5579   const char *text = "<?xml version='1.0' encoding='failing-conv'?>\n"
5580                      "<doc>\x81</doc>";
5581 
5582   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5583   /* BadEncodingHandler sets up an encoding with every top-bit-set
5584    * character introducing a two-byte sequence.  For this, it
5585    * requires a convert function.  The above function call passes
5586    * one that insists all possible sequences are invalid anyway.
5587    */
5588   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5589                  "Encoding with failing convert() not faulted");
5590 }
5591 END_TEST
5592 
5593 /* Test unknown encoding conversions */
START_TEST(test_unknown_encoding_success)5594 START_TEST(test_unknown_encoding_success) {
5595   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5596                      /* Equivalent to <eoc>Hello, world</eoc> */
5597                      "<\x81\x64\x80oc>Hello, world</\x81\x64\x80oc>";
5598 
5599   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5600   run_character_check(text, XCS("Hello, world"));
5601 }
5602 END_TEST
5603 
5604 /* Test bad name character in unknown encoding */
START_TEST(test_unknown_encoding_bad_name)5605 START_TEST(test_unknown_encoding_bad_name) {
5606   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5607                      "<\xff\x64oc>Hello, world</\xff\x64oc>";
5608 
5609   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5610   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5611                  "Bad name start in unknown encoding not faulted");
5612 }
5613 END_TEST
5614 
5615 /* Test bad mid-name character in unknown encoding */
START_TEST(test_unknown_encoding_bad_name_2)5616 START_TEST(test_unknown_encoding_bad_name_2) {
5617   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5618                      "<d\xffoc>Hello, world</d\xffoc>";
5619 
5620   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5621   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5622                  "Bad name in unknown encoding not faulted");
5623 }
5624 END_TEST
5625 
5626 /* Test element name that is long enough to fill the conversion buffer
5627  * in an unknown encoding, finishing with an encoded character.
5628  */
START_TEST(test_unknown_encoding_long_name_1)5629 START_TEST(test_unknown_encoding_long_name_1) {
5630   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5631                      "<abcdefghabcdefghabcdefghijkl\x80m\x80n\x80o\x80p>"
5632                      "Hi"
5633                      "</abcdefghabcdefghabcdefghijkl\x80m\x80n\x80o\x80p>";
5634   const XML_Char *expected = XCS("abcdefghabcdefghabcdefghijklmnop");
5635   CharData storage;
5636 
5637   CharData_Init(&storage);
5638   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5639   XML_SetStartElementHandler(g_parser, record_element_start_handler);
5640   XML_SetUserData(g_parser, &storage);
5641   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5642       == XML_STATUS_ERROR)
5643     xml_failure(g_parser);
5644   CharData_CheckXMLChars(&storage, expected);
5645 }
5646 END_TEST
5647 
5648 /* Test element name that is long enough to fill the conversion buffer
5649  * in an unknown encoding, finishing with an simple character.
5650  */
START_TEST(test_unknown_encoding_long_name_2)5651 START_TEST(test_unknown_encoding_long_name_2) {
5652   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5653                      "<abcdefghabcdefghabcdefghijklmnop>"
5654                      "Hi"
5655                      "</abcdefghabcdefghabcdefghijklmnop>";
5656   const XML_Char *expected = XCS("abcdefghabcdefghabcdefghijklmnop");
5657   CharData storage;
5658 
5659   CharData_Init(&storage);
5660   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5661   XML_SetStartElementHandler(g_parser, record_element_start_handler);
5662   XML_SetUserData(g_parser, &storage);
5663   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5664       == XML_STATUS_ERROR)
5665     xml_failure(g_parser);
5666   CharData_CheckXMLChars(&storage, expected);
5667 }
5668 END_TEST
5669 
START_TEST(test_invalid_unknown_encoding)5670 START_TEST(test_invalid_unknown_encoding) {
5671   const char *text = "<?xml version='1.0' encoding='invalid-9'?>\n"
5672                      "<doc>Hello world</doc>";
5673 
5674   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5675   expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5676                  "Invalid unknown encoding not faulted");
5677 }
5678 END_TEST
5679 
START_TEST(test_unknown_ascii_encoding_ok)5680 START_TEST(test_unknown_ascii_encoding_ok) {
5681   const char *text = "<?xml version='1.0' encoding='ascii-like'?>\n"
5682                      "<doc>Hello, world</doc>";
5683 
5684   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5685   run_character_check(text, XCS("Hello, world"));
5686 }
5687 END_TEST
5688 
START_TEST(test_unknown_ascii_encoding_fail)5689 START_TEST(test_unknown_ascii_encoding_fail) {
5690   const char *text = "<?xml version='1.0' encoding='ascii-like'?>\n"
5691                      "<doc>Hello, \x80 world</doc>";
5692 
5693   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5694   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5695                  "Invalid character not faulted");
5696 }
5697 END_TEST
5698 
START_TEST(test_unknown_encoding_invalid_length)5699 START_TEST(test_unknown_encoding_invalid_length) {
5700   const char *text = "<?xml version='1.0' encoding='invalid-len'?>\n"
5701                      "<doc>Hello, world</doc>";
5702 
5703   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5704   expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5705                  "Invalid unknown encoding not faulted");
5706 }
5707 END_TEST
5708 
START_TEST(test_unknown_encoding_invalid_topbit)5709 START_TEST(test_unknown_encoding_invalid_topbit) {
5710   const char *text = "<?xml version='1.0' encoding='invalid-a'?>\n"
5711                      "<doc>Hello, world</doc>";
5712 
5713   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5714   expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5715                  "Invalid unknown encoding not faulted");
5716 }
5717 END_TEST
5718 
START_TEST(test_unknown_encoding_invalid_surrogate)5719 START_TEST(test_unknown_encoding_invalid_surrogate) {
5720   const char *text = "<?xml version='1.0' encoding='invalid-surrogate'?>\n"
5721                      "<doc>Hello, \x82 world</doc>";
5722 
5723   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5724   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5725                  "Invalid unknown encoding not faulted");
5726 }
5727 END_TEST
5728 
START_TEST(test_unknown_encoding_invalid_high)5729 START_TEST(test_unknown_encoding_invalid_high) {
5730   const char *text = "<?xml version='1.0' encoding='invalid-high'?>\n"
5731                      "<doc>Hello, world</doc>";
5732 
5733   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5734   expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5735                  "Invalid unknown encoding not faulted");
5736 }
5737 END_TEST
5738 
START_TEST(test_unknown_encoding_invalid_attr_value)5739 START_TEST(test_unknown_encoding_invalid_attr_value) {
5740   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5741                      "<doc attr='\xff\x30'/>";
5742 
5743   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5744   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5745                  "Invalid attribute valid not faulted");
5746 }
5747 END_TEST
5748 
5749 /* Test an external entity parser set to use latin-1 detects UTF-16
5750  * BOMs correctly.
5751  */
5752 enum ee_parse_flags { EE_PARSE_NONE = 0x00, EE_PARSE_FULL_BUFFER = 0x01 };
5753 
5754 typedef struct ExtTest2 {
5755   const char *parse_text;
5756   int parse_len;
5757   const XML_Char *encoding;
5758   CharData *storage;
5759   enum ee_parse_flags flags;
5760 } ExtTest2;
5761 
5762 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)5763 external_entity_loader2(XML_Parser parser, const XML_Char *context,
5764                         const XML_Char *base, const XML_Char *systemId,
5765                         const XML_Char *publicId) {
5766   ExtTest2 *test_data = (ExtTest2 *)XML_GetUserData(parser);
5767   XML_Parser extparser;
5768 
5769   UNUSED_P(base);
5770   UNUSED_P(systemId);
5771   UNUSED_P(publicId);
5772   extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
5773   if (extparser == NULL)
5774     fail("Coulr not create external entity parser");
5775   if (test_data->encoding != NULL) {
5776     if (! XML_SetEncoding(extparser, test_data->encoding))
5777       fail("XML_SetEncoding() ignored for external entity");
5778   }
5779   if (test_data->flags & EE_PARSE_FULL_BUFFER) {
5780     if (XML_Parse(extparser, test_data->parse_text, test_data->parse_len,
5781                   XML_TRUE)
5782         == XML_STATUS_ERROR) {
5783       xml_failure(extparser);
5784     }
5785   } else if (_XML_Parse_SINGLE_BYTES(extparser, test_data->parse_text,
5786                                      test_data->parse_len, XML_TRUE)
5787              == XML_STATUS_ERROR) {
5788     xml_failure(extparser);
5789   }
5790 
5791   XML_ParserFree(extparser);
5792   return XML_STATUS_OK;
5793 }
5794 
5795 /* Test that UTF-16 BOM does not select UTF-16 given explicit encoding */
5796 static void XMLCALL
ext2_accumulate_characters(void * userData,const XML_Char * s,int len)5797 ext2_accumulate_characters(void *userData, const XML_Char *s, int len) {
5798   ExtTest2 *test_data = (ExtTest2 *)userData;
5799   accumulate_characters(test_data->storage, s, len);
5800 }
5801 
START_TEST(test_ext_entity_latin1_utf16le_bom)5802 START_TEST(test_ext_entity_latin1_utf16le_bom) {
5803   const char *text = "<!DOCTYPE doc [\n"
5804                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5805                      "]>\n"
5806                      "<doc>&en;</doc>";
5807   ExtTest2 test_data
5808       = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */
5809          /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn,
5810           *   0x4c = L and 0x20 is a space
5811           */
5812          "\xff\xfe\x4c\x20", 4, XCS("iso-8859-1"), NULL, EE_PARSE_NONE};
5813 #ifdef XML_UNICODE
5814   const XML_Char *expected = XCS("\x00ff\x00feL ");
5815 #else
5816   /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */
5817   const XML_Char *expected = XCS("\xc3\xbf\xc3\xbeL ");
5818 #endif
5819   CharData storage;
5820 
5821   CharData_Init(&storage);
5822   test_data.storage = &storage;
5823   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5824   XML_SetUserData(g_parser, &test_data);
5825   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5826   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5827       == XML_STATUS_ERROR)
5828     xml_failure(g_parser);
5829   CharData_CheckXMLChars(&storage, expected);
5830 }
5831 END_TEST
5832 
START_TEST(test_ext_entity_latin1_utf16be_bom)5833 START_TEST(test_ext_entity_latin1_utf16be_bom) {
5834   const char *text = "<!DOCTYPE doc [\n"
5835                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5836                      "]>\n"
5837                      "<doc>&en;</doc>";
5838   ExtTest2 test_data
5839       = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */
5840          /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn,
5841           *   0x4c = L and 0x20 is a space
5842           */
5843          "\xfe\xff\x20\x4c", 4, XCS("iso-8859-1"), NULL, EE_PARSE_NONE};
5844 #ifdef XML_UNICODE
5845   const XML_Char *expected = XCS("\x00fe\x00ff L");
5846 #else
5847   /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */
5848   const XML_Char *expected = XCS("\xc3\xbe\xc3\xbf L");
5849 #endif
5850   CharData storage;
5851 
5852   CharData_Init(&storage);
5853   test_data.storage = &storage;
5854   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5855   XML_SetUserData(g_parser, &test_data);
5856   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5857   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5858       == XML_STATUS_ERROR)
5859     xml_failure(g_parser);
5860   CharData_CheckXMLChars(&storage, expected);
5861 }
5862 END_TEST
5863 
5864 /* Parsing the full buffer rather than a byte at a time makes a
5865  * difference to the encoding scanning code, so repeat the above tests
5866  * without breaking them down by byte.
5867  */
START_TEST(test_ext_entity_latin1_utf16le_bom2)5868 START_TEST(test_ext_entity_latin1_utf16le_bom2) {
5869   const char *text = "<!DOCTYPE doc [\n"
5870                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5871                      "]>\n"
5872                      "<doc>&en;</doc>";
5873   ExtTest2 test_data
5874       = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */
5875          /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn,
5876           *   0x4c = L and 0x20 is a space
5877           */
5878          "\xff\xfe\x4c\x20", 4, XCS("iso-8859-1"), NULL, EE_PARSE_FULL_BUFFER};
5879 #ifdef XML_UNICODE
5880   const XML_Char *expected = XCS("\x00ff\x00feL ");
5881 #else
5882   /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */
5883   const XML_Char *expected = XCS("\xc3\xbf\xc3\xbeL ");
5884 #endif
5885   CharData storage;
5886 
5887   CharData_Init(&storage);
5888   test_data.storage = &storage;
5889   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5890   XML_SetUserData(g_parser, &test_data);
5891   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5892   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
5893       == XML_STATUS_ERROR)
5894     xml_failure(g_parser);
5895   CharData_CheckXMLChars(&storage, expected);
5896 }
5897 END_TEST
5898 
START_TEST(test_ext_entity_latin1_utf16be_bom2)5899 START_TEST(test_ext_entity_latin1_utf16be_bom2) {
5900   const char *text = "<!DOCTYPE doc [\n"
5901                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5902                      "]>\n"
5903                      "<doc>&en;</doc>";
5904   ExtTest2 test_data
5905       = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */
5906          /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn,
5907           *   0x4c = L and 0x20 is a space
5908           */
5909          "\xfe\xff\x20\x4c", 4, XCS("iso-8859-1"), NULL, EE_PARSE_FULL_BUFFER};
5910 #ifdef XML_UNICODE
5911   const XML_Char *expected = XCS("\x00fe\x00ff L");
5912 #else
5913   /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */
5914   const XML_Char *expected = "\xc3\xbe\xc3\xbf L";
5915 #endif
5916   CharData storage;
5917 
5918   CharData_Init(&storage);
5919   test_data.storage = &storage;
5920   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5921   XML_SetUserData(g_parser, &test_data);
5922   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5923   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
5924       == XML_STATUS_ERROR)
5925     xml_failure(g_parser);
5926   CharData_CheckXMLChars(&storage, expected);
5927 }
5928 END_TEST
5929 
5930 /* Test little-endian UTF-16 given an explicit big-endian encoding */
START_TEST(test_ext_entity_utf16_be)5931 START_TEST(test_ext_entity_utf16_be) {
5932   const char *text = "<!DOCTYPE doc [\n"
5933                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5934                      "]>\n"
5935                      "<doc>&en;</doc>";
5936   ExtTest2 test_data
5937       = {"<\0e\0/\0>\0", 8, XCS("utf-16be"), NULL, EE_PARSE_NONE};
5938 #ifdef XML_UNICODE
5939   const XML_Char *expected = XCS("\x3c00\x6500\x2f00\x3e00");
5940 #else
5941   const XML_Char *expected = XCS("\xe3\xb0\x80"   /* U+3C00 */
5942                                  "\xe6\x94\x80"   /* U+6500 */
5943                                  "\xe2\xbc\x80"   /* U+2F00 */
5944                                  "\xe3\xb8\x80"); /* U+3E00 */
5945 #endif
5946   CharData storage;
5947 
5948   CharData_Init(&storage);
5949   test_data.storage = &storage;
5950   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5951   XML_SetUserData(g_parser, &test_data);
5952   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5953   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5954       == XML_STATUS_ERROR)
5955     xml_failure(g_parser);
5956   CharData_CheckXMLChars(&storage, expected);
5957 }
5958 END_TEST
5959 
5960 /* Test big-endian UTF-16 given an explicit little-endian encoding */
START_TEST(test_ext_entity_utf16_le)5961 START_TEST(test_ext_entity_utf16_le) {
5962   const char *text = "<!DOCTYPE doc [\n"
5963                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5964                      "]>\n"
5965                      "<doc>&en;</doc>";
5966   ExtTest2 test_data
5967       = {"\0<\0e\0/\0>", 8, XCS("utf-16le"), NULL, EE_PARSE_NONE};
5968 #ifdef XML_UNICODE
5969   const XML_Char *expected = XCS("\x3c00\x6500\x2f00\x3e00");
5970 #else
5971   const XML_Char *expected = XCS("\xe3\xb0\x80"   /* U+3C00 */
5972                                  "\xe6\x94\x80"   /* U+6500 */
5973                                  "\xe2\xbc\x80"   /* U+2F00 */
5974                                  "\xe3\xb8\x80"); /* U+3E00 */
5975 #endif
5976   CharData storage;
5977 
5978   CharData_Init(&storage);
5979   test_data.storage = &storage;
5980   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5981   XML_SetUserData(g_parser, &test_data);
5982   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5983   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5984       == XML_STATUS_ERROR)
5985     xml_failure(g_parser);
5986   CharData_CheckXMLChars(&storage, expected);
5987 }
5988 END_TEST
5989 
5990 /* Test little-endian UTF-16 given no explicit encoding.
5991  * The existing default encoding (UTF-8) is assumed to hold without a
5992  * BOM to contradict it, so the entity value will in fact provoke an
5993  * error because 0x00 is not a valid XML character.  We parse the
5994  * whole buffer in one go rather than feeding it in byte by byte to
5995  * exercise different code paths in the initial scanning routines.
5996  */
5997 typedef struct ExtFaults2 {
5998   const char *parse_text;
5999   int parse_len;
6000   const char *fail_text;
6001   const XML_Char *encoding;
6002   enum XML_Error error;
6003 } ExtFaults2;
6004 
6005 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)6006 external_entity_faulter2(XML_Parser parser, const XML_Char *context,
6007                          const XML_Char *base, const XML_Char *systemId,
6008                          const XML_Char *publicId) {
6009   ExtFaults2 *test_data = (ExtFaults2 *)XML_GetUserData(parser);
6010   XML_Parser extparser;
6011 
6012   UNUSED_P(base);
6013   UNUSED_P(systemId);
6014   UNUSED_P(publicId);
6015   extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
6016   if (extparser == NULL)
6017     fail("Could not create external entity parser");
6018   if (test_data->encoding != NULL) {
6019     if (! XML_SetEncoding(extparser, test_data->encoding))
6020       fail("XML_SetEncoding() ignored for external entity");
6021   }
6022   if (XML_Parse(extparser, test_data->parse_text, test_data->parse_len,
6023                 XML_TRUE)
6024       != XML_STATUS_ERROR)
6025     fail(test_data->fail_text);
6026   if (XML_GetErrorCode(extparser) != test_data->error)
6027     xml_failure(extparser);
6028 
6029   XML_ParserFree(extparser);
6030   return XML_STATUS_ERROR;
6031 }
6032 
START_TEST(test_ext_entity_utf16_unknown)6033 START_TEST(test_ext_entity_utf16_unknown) {
6034   const char *text = "<!DOCTYPE doc [\n"
6035                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
6036                      "]>\n"
6037                      "<doc>&en;</doc>";
6038   ExtFaults2 test_data
6039       = {"a\0b\0c\0", 6, "Invalid character in entity not faulted", NULL,
6040          XML_ERROR_INVALID_TOKEN};
6041 
6042   XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter2);
6043   XML_SetUserData(g_parser, &test_data);
6044   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
6045                  "Invalid character should not have been accepted");
6046 }
6047 END_TEST
6048 
6049 /* Test not-quite-UTF-8 BOM (0xEF 0xBB 0xBF) */
START_TEST(test_ext_entity_utf8_non_bom)6050 START_TEST(test_ext_entity_utf8_non_bom) {
6051   const char *text = "<!DOCTYPE doc [\n"
6052                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
6053                      "]>\n"
6054                      "<doc>&en;</doc>";
6055   ExtTest2 test_data
6056       = {"\xef\xbb\x80", /* Arabic letter DAD medial form, U+FEC0 */
6057          3, NULL, NULL, EE_PARSE_NONE};
6058 #ifdef XML_UNICODE
6059   const XML_Char *expected = XCS("\xfec0");
6060 #else
6061   const XML_Char *expected = XCS("\xef\xbb\x80");
6062 #endif
6063   CharData storage;
6064 
6065   CharData_Init(&storage);
6066   test_data.storage = &storage;
6067   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
6068   XML_SetUserData(g_parser, &test_data);
6069   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
6070   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6071       == XML_STATUS_ERROR)
6072     xml_failure(g_parser);
6073   CharData_CheckXMLChars(&storage, expected);
6074 }
6075 END_TEST
6076 
6077 /* Test that UTF-8 in a CDATA section is correctly passed through */
START_TEST(test_utf8_in_cdata_section)6078 START_TEST(test_utf8_in_cdata_section) {
6079   const char *text = "<doc><![CDATA[one \xc3\xa9 two]]></doc>";
6080 #ifdef XML_UNICODE
6081   const XML_Char *expected = XCS("one \x00e9 two");
6082 #else
6083   const XML_Char *expected = XCS("one \xc3\xa9 two");
6084 #endif
6085 
6086   run_character_check(text, expected);
6087 }
6088 END_TEST
6089 
6090 /* Test that little-endian UTF-16 in a CDATA section is handled */
START_TEST(test_utf8_in_cdata_section_2)6091 START_TEST(test_utf8_in_cdata_section_2) {
6092   const char *text = "<doc><![CDATA[\xc3\xa9]\xc3\xa9two]]></doc>";
6093 #ifdef XML_UNICODE
6094   const XML_Char *expected = XCS("\x00e9]\x00e9two");
6095 #else
6096   const XML_Char *expected = XCS("\xc3\xa9]\xc3\xa9two");
6097 #endif
6098 
6099   run_character_check(text, expected);
6100 }
6101 END_TEST
6102 
6103 /* Test trailing spaces in elements are accepted */
6104 static void XMLCALL
record_element_end_handler(void * userData,const XML_Char * name)6105 record_element_end_handler(void *userData, const XML_Char *name) {
6106   CharData *storage = (CharData *)userData;
6107 
6108   CharData_AppendXMLChars(storage, XCS("/"), 1);
6109   CharData_AppendXMLChars(storage, name, -1);
6110 }
6111 
START_TEST(test_trailing_spaces_in_elements)6112 START_TEST(test_trailing_spaces_in_elements) {
6113   const char *text = "<doc   >Hi</doc >";
6114   const XML_Char *expected = XCS("doc/doc");
6115   CharData storage;
6116 
6117   CharData_Init(&storage);
6118   XML_SetElementHandler(g_parser, record_element_start_handler,
6119                         record_element_end_handler);
6120   XML_SetUserData(g_parser, &storage);
6121   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6122       == XML_STATUS_ERROR)
6123     xml_failure(g_parser);
6124   CharData_CheckXMLChars(&storage, expected);
6125 }
6126 END_TEST
6127 
START_TEST(test_utf16_attribute)6128 START_TEST(test_utf16_attribute) {
6129   const char text[] =
6130       /* <d {KHO KHWAI}{CHO CHAN}='a'/>
6131        * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
6132        * and   {CHO CHAN}  = U+0E08 = 0xe0 0xb8 0x88 in UTF-8
6133        */
6134       "<\0d\0 \0\x04\x0e\x08\x0e=\0'\0a\0'\0/\0>\0";
6135   const XML_Char *expected = XCS("a");
6136   CharData storage;
6137 
6138   CharData_Init(&storage);
6139   XML_SetStartElementHandler(g_parser, accumulate_attribute);
6140   XML_SetUserData(g_parser, &storage);
6141   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6142       == XML_STATUS_ERROR)
6143     xml_failure(g_parser);
6144   CharData_CheckXMLChars(&storage, expected);
6145 }
6146 END_TEST
6147 
START_TEST(test_utf16_second_attr)6148 START_TEST(test_utf16_second_attr) {
6149   /* <d a='1' {KHO KHWAI}{CHO CHAN}='2'/>
6150    * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
6151    * and   {CHO CHAN}  = U+0E08 = 0xe0 0xb8 0x88 in UTF-8
6152    */
6153   const char text[] = "<\0d\0 \0a\0=\0'\0\x31\0'\0 \0"
6154                       "\x04\x0e\x08\x0e=\0'\0\x32\0'\0/\0>\0";
6155   const XML_Char *expected = XCS("1");
6156   CharData storage;
6157 
6158   CharData_Init(&storage);
6159   XML_SetStartElementHandler(g_parser, accumulate_attribute);
6160   XML_SetUserData(g_parser, &storage);
6161   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6162       == XML_STATUS_ERROR)
6163     xml_failure(g_parser);
6164   CharData_CheckXMLChars(&storage, expected);
6165 }
6166 END_TEST
6167 
START_TEST(test_attr_after_solidus)6168 START_TEST(test_attr_after_solidus) {
6169   const char *text = "<doc attr1='a' / attr2='b'>";
6170 
6171   expect_failure(text, XML_ERROR_INVALID_TOKEN, "Misplaced / not faulted");
6172 }
6173 END_TEST
6174 
6175 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)6176 accumulate_entity_decl(void *userData, const XML_Char *entityName,
6177                        int is_parameter_entity, const XML_Char *value,
6178                        int value_length, const XML_Char *base,
6179                        const XML_Char *systemId, const XML_Char *publicId,
6180                        const XML_Char *notationName) {
6181   CharData *storage = (CharData *)userData;
6182 
6183   UNUSED_P(is_parameter_entity);
6184   UNUSED_P(base);
6185   UNUSED_P(systemId);
6186   UNUSED_P(publicId);
6187   UNUSED_P(notationName);
6188   CharData_AppendXMLChars(storage, entityName, -1);
6189   CharData_AppendXMLChars(storage, XCS("="), 1);
6190   CharData_AppendXMLChars(storage, value, value_length);
6191   CharData_AppendXMLChars(storage, XCS("\n"), 1);
6192 }
6193 
START_TEST(test_utf16_pe)6194 START_TEST(test_utf16_pe) {
6195   /* <!DOCTYPE doc [
6196    * <!ENTITY % {KHO KHWAI}{CHO CHAN} '<!ELEMENT doc (#PCDATA)>'>
6197    * %{KHO KHWAI}{CHO CHAN};
6198    * ]>
6199    * <doc></doc>
6200    *
6201    * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
6202    * and   {CHO CHAN}  = U+0E08 = 0xe0 0xb8 0x88 in UTF-8
6203    */
6204   const char text[] = "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0\n"
6205                       "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \x0e\x04\x0e\x08\0 "
6206                       "\0'\0<\0!\0E\0L\0E\0M\0E\0N\0T\0 "
6207                       "\0d\0o\0c\0 \0(\0#\0P\0C\0D\0A\0T\0A\0)\0>\0'\0>\0\n"
6208                       "\0%\x0e\x04\x0e\x08\0;\0\n"
6209                       "\0]\0>\0\n"
6210                       "\0<\0d\0o\0c\0>\0<\0/\0d\0o\0c\0>";
6211 #ifdef XML_UNICODE
6212   const XML_Char *expected = XCS("\x0e04\x0e08=<!ELEMENT doc (#PCDATA)>\n");
6213 #else
6214   const XML_Char *expected
6215       = XCS("\xe0\xb8\x84\xe0\xb8\x88=<!ELEMENT doc (#PCDATA)>\n");
6216 #endif
6217   CharData storage;
6218 
6219   CharData_Init(&storage);
6220   XML_SetUserData(g_parser, &storage);
6221   XML_SetEntityDeclHandler(g_parser, accumulate_entity_decl);
6222   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6223       == XML_STATUS_ERROR)
6224     xml_failure(g_parser);
6225   CharData_CheckXMLChars(&storage, expected);
6226 }
6227 END_TEST
6228 
6229 /* Test that duff attribute description keywords are rejected */
START_TEST(test_bad_attr_desc_keyword)6230 START_TEST(test_bad_attr_desc_keyword) {
6231   const char *text = "<!DOCTYPE doc [\n"
6232                      "  <!ATTLIST doc attr CDATA #!IMPLIED>\n"
6233                      "]>\n"
6234                      "<doc />";
6235 
6236   expect_failure(text, XML_ERROR_INVALID_TOKEN,
6237                  "Bad keyword !IMPLIED not faulted");
6238 }
6239 END_TEST
6240 
6241 /* Test that an invalid attribute description keyword consisting of
6242  * UTF-16 characters with their top bytes non-zero are correctly
6243  * faulted
6244  */
START_TEST(test_bad_attr_desc_keyword_utf16)6245 START_TEST(test_bad_attr_desc_keyword_utf16) {
6246   /* <!DOCTYPE d [
6247    * <!ATTLIST d a CDATA #{KHO KHWAI}{CHO CHAN}>
6248    * ]><d/>
6249    *
6250    * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
6251    * and   {CHO CHAN}  = U+0E08 = 0xe0 0xb8 0x88 in UTF-8
6252    */
6253   const char text[]
6254       = "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n"
6255         "\0<\0!\0A\0T\0T\0L\0I\0S\0T\0 \0d\0 \0a\0 \0C\0D\0A\0T\0A\0 "
6256         "\0#\x0e\x04\x0e\x08\0>\0\n"
6257         "\0]\0>\0<\0d\0/\0>";
6258 
6259   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6260       != XML_STATUS_ERROR)
6261     fail("Invalid UTF16 attribute keyword not faulted");
6262   if (XML_GetErrorCode(g_parser) != XML_ERROR_SYNTAX)
6263     xml_failure(g_parser);
6264 }
6265 END_TEST
6266 
6267 /* Test that invalid syntax in a <!DOCTYPE> is rejected.  Do this
6268  * using prefix-encoding (see above) to trigger specific code paths
6269  */
START_TEST(test_bad_doctype)6270 START_TEST(test_bad_doctype) {
6271   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
6272                      "<!DOCTYPE doc [ \x80\x44 ]><doc/>";
6273 
6274   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
6275   expect_failure(text, XML_ERROR_SYNTAX,
6276                  "Invalid bytes in DOCTYPE not faulted");
6277 }
6278 END_TEST
6279 
START_TEST(test_bad_doctype_utf16)6280 START_TEST(test_bad_doctype_utf16) {
6281   const char text[] =
6282       /* <!DOCTYPE doc [ \x06f2 ]><doc/>
6283        *
6284        * U+06F2 = EXTENDED ARABIC-INDIC DIGIT TWO, a valid number
6285        * (name character) but not a valid letter (name start character)
6286        */
6287       "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0 "
6288       "\x06\xf2"
6289       "\0 \0]\0>\0<\0d\0o\0c\0/\0>";
6290 
6291   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6292       != XML_STATUS_ERROR)
6293     fail("Invalid bytes in DOCTYPE not faulted");
6294   if (XML_GetErrorCode(g_parser) != XML_ERROR_SYNTAX)
6295     xml_failure(g_parser);
6296 }
6297 END_TEST
6298 
START_TEST(test_bad_doctype_plus)6299 START_TEST(test_bad_doctype_plus) {
6300   const char *text = "<!DOCTYPE 1+ [ <!ENTITY foo 'bar'> ]>\n"
6301                      "<1+>&foo;</1+>";
6302 
6303   expect_failure(text, XML_ERROR_INVALID_TOKEN,
6304                  "'+' in document name not faulted");
6305 }
6306 END_TEST
6307 
START_TEST(test_bad_doctype_star)6308 START_TEST(test_bad_doctype_star) {
6309   const char *text = "<!DOCTYPE 1* [ <!ENTITY foo 'bar'> ]>\n"
6310                      "<1*>&foo;</1*>";
6311 
6312   expect_failure(text, XML_ERROR_INVALID_TOKEN,
6313                  "'*' in document name not faulted");
6314 }
6315 END_TEST
6316 
START_TEST(test_bad_doctype_query)6317 START_TEST(test_bad_doctype_query) {
6318   const char *text = "<!DOCTYPE 1? [ <!ENTITY foo 'bar'> ]>\n"
6319                      "<1?>&foo;</1?>";
6320 
6321   expect_failure(text, XML_ERROR_INVALID_TOKEN,
6322                  "'?' in document name not faulted");
6323 }
6324 END_TEST
6325 
START_TEST(test_unknown_encoding_bad_ignore)6326 START_TEST(test_unknown_encoding_bad_ignore) {
6327   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>"
6328                      "<!DOCTYPE doc SYSTEM 'foo'>"
6329                      "<doc><e>&entity;</e></doc>";
6330   ExtFaults fault = {"<![IGNORE[<!ELEMENT \xffG (#PCDATA)*>]]>",
6331                      "Invalid character not faulted", XCS("prefix-conv"),
6332                      XML_ERROR_INVALID_TOKEN};
6333 
6334   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
6335   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6336   XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
6337   XML_SetUserData(g_parser, &fault);
6338   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
6339                  "Bad IGNORE section with unknown encoding not failed");
6340 }
6341 END_TEST
6342 
START_TEST(test_entity_in_utf16_be_attr)6343 START_TEST(test_entity_in_utf16_be_attr) {
6344   const char text[] =
6345       /* <e a='&#228; &#x00E4;'></e> */
6346       "\0<\0e\0 \0a\0=\0'\0&\0#\0\x32\0\x32\0\x38\0;\0 "
6347       "\0&\0#\0x\0\x30\0\x30\0E\0\x34\0;\0'\0>\0<\0/\0e\0>";
6348 #ifdef XML_UNICODE
6349   const XML_Char *expected = XCS("\x00e4 \x00e4");
6350 #else
6351   const XML_Char *expected = XCS("\xc3\xa4 \xc3\xa4");
6352 #endif
6353   CharData storage;
6354 
6355   CharData_Init(&storage);
6356   XML_SetUserData(g_parser, &storage);
6357   XML_SetStartElementHandler(g_parser, accumulate_attribute);
6358   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6359       == XML_STATUS_ERROR)
6360     xml_failure(g_parser);
6361   CharData_CheckXMLChars(&storage, expected);
6362 }
6363 END_TEST
6364 
START_TEST(test_entity_in_utf16_le_attr)6365 START_TEST(test_entity_in_utf16_le_attr) {
6366   const char text[] =
6367       /* <e a='&#228; &#x00E4;'></e> */
6368       "<\0e\0 \0a\0=\0'\0&\0#\0\x32\0\x32\0\x38\0;\0 \0"
6369       "&\0#\0x\0\x30\0\x30\0E\0\x34\0;\0'\0>\0<\0/\0e\0>\0";
6370 #ifdef XML_UNICODE
6371   const XML_Char *expected = XCS("\x00e4 \x00e4");
6372 #else
6373   const XML_Char *expected = XCS("\xc3\xa4 \xc3\xa4");
6374 #endif
6375   CharData storage;
6376 
6377   CharData_Init(&storage);
6378   XML_SetUserData(g_parser, &storage);
6379   XML_SetStartElementHandler(g_parser, accumulate_attribute);
6380   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6381       == XML_STATUS_ERROR)
6382     xml_failure(g_parser);
6383   CharData_CheckXMLChars(&storage, expected);
6384 }
6385 END_TEST
6386 
START_TEST(test_entity_public_utf16_be)6387 START_TEST(test_entity_public_utf16_be) {
6388   const char text[] =
6389       /* <!DOCTYPE d [ */
6390       "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n"
6391       /* <!ENTITY % e PUBLIC 'foo' 'bar.ent'> */
6392       "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \0e\0 \0P\0U\0B\0L\0I\0C\0 "
6393       "\0'\0f\0o\0o\0'\0 \0'\0b\0a\0r\0.\0e\0n\0t\0'\0>\0\n"
6394       /* %e; */
6395       "\0%\0e\0;\0\n"
6396       /* ]> */
6397       "\0]\0>\0\n"
6398       /* <d>&j;</d> */
6399       "\0<\0d\0>\0&\0j\0;\0<\0/\0d\0>";
6400   ExtTest2 test_data = {/* <!ENTITY j 'baz'> */
6401                         "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0j\0 \0'\0b\0a\0z\0'\0>",
6402                         34, NULL, NULL, EE_PARSE_NONE};
6403   const XML_Char *expected = XCS("baz");
6404   CharData storage;
6405 
6406   CharData_Init(&storage);
6407   test_data.storage = &storage;
6408   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6409   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
6410   XML_SetUserData(g_parser, &test_data);
6411   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
6412   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6413       == XML_STATUS_ERROR)
6414     xml_failure(g_parser);
6415   CharData_CheckXMLChars(&storage, expected);
6416 }
6417 END_TEST
6418 
START_TEST(test_entity_public_utf16_le)6419 START_TEST(test_entity_public_utf16_le) {
6420   const char text[] =
6421       /* <!DOCTYPE d [ */
6422       "<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n\0"
6423       /* <!ENTITY % e PUBLIC 'foo' 'bar.ent'> */
6424       "<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \0e\0 \0P\0U\0B\0L\0I\0C\0 \0"
6425       "'\0f\0o\0o\0'\0 \0'\0b\0a\0r\0.\0e\0n\0t\0'\0>\0\n\0"
6426       /* %e; */
6427       "%\0e\0;\0\n\0"
6428       /* ]> */
6429       "]\0>\0\n\0"
6430       /* <d>&j;</d> */
6431       "<\0d\0>\0&\0j\0;\0<\0/\0d\0>\0";
6432   ExtTest2 test_data = {/* <!ENTITY j 'baz'> */
6433                         "<\0!\0E\0N\0T\0I\0T\0Y\0 \0j\0 \0'\0b\0a\0z\0'\0>\0",
6434                         34, NULL, NULL, EE_PARSE_NONE};
6435   const XML_Char *expected = XCS("baz");
6436   CharData storage;
6437 
6438   CharData_Init(&storage);
6439   test_data.storage = &storage;
6440   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6441   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
6442   XML_SetUserData(g_parser, &test_data);
6443   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
6444   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6445       == XML_STATUS_ERROR)
6446     xml_failure(g_parser);
6447   CharData_CheckXMLChars(&storage, expected);
6448 }
6449 END_TEST
6450 
6451 /* Test that a doctype with neither an internal nor external subset is
6452  * faulted
6453  */
START_TEST(test_short_doctype)6454 START_TEST(test_short_doctype) {
6455   const char *text = "<!DOCTYPE doc></doc>";
6456   expect_failure(text, XML_ERROR_INVALID_TOKEN,
6457                  "DOCTYPE without subset not rejected");
6458 }
6459 END_TEST
6460 
START_TEST(test_short_doctype_2)6461 START_TEST(test_short_doctype_2) {
6462   const char *text = "<!DOCTYPE doc PUBLIC></doc>";
6463   expect_failure(text, XML_ERROR_SYNTAX,
6464                  "DOCTYPE without Public ID not rejected");
6465 }
6466 END_TEST
6467 
START_TEST(test_short_doctype_3)6468 START_TEST(test_short_doctype_3) {
6469   const char *text = "<!DOCTYPE doc SYSTEM></doc>";
6470   expect_failure(text, XML_ERROR_SYNTAX,
6471                  "DOCTYPE without System ID not rejected");
6472 }
6473 END_TEST
6474 
START_TEST(test_long_doctype)6475 START_TEST(test_long_doctype) {
6476   const char *text = "<!DOCTYPE doc PUBLIC 'foo' 'bar' 'baz'></doc>";
6477   expect_failure(text, XML_ERROR_SYNTAX, "DOCTYPE with extra ID not rejected");
6478 }
6479 END_TEST
6480 
START_TEST(test_bad_entity)6481 START_TEST(test_bad_entity) {
6482   const char *text = "<!DOCTYPE doc [\n"
6483                      "  <!ENTITY foo PUBLIC>\n"
6484                      "]>\n"
6485                      "<doc/>";
6486   expect_failure(text, XML_ERROR_SYNTAX,
6487                  "ENTITY without Public ID is not rejected");
6488 }
6489 END_TEST
6490 
6491 /* Test unquoted value is faulted */
START_TEST(test_bad_entity_2)6492 START_TEST(test_bad_entity_2) {
6493   const char *text = "<!DOCTYPE doc [\n"
6494                      "  <!ENTITY % foo bar>\n"
6495                      "]>\n"
6496                      "<doc/>";
6497   expect_failure(text, XML_ERROR_SYNTAX,
6498                  "ENTITY without Public ID is not rejected");
6499 }
6500 END_TEST
6501 
START_TEST(test_bad_entity_3)6502 START_TEST(test_bad_entity_3) {
6503   const char *text = "<!DOCTYPE doc [\n"
6504                      "  <!ENTITY % foo PUBLIC>\n"
6505                      "]>\n"
6506                      "<doc/>";
6507   expect_failure(text, XML_ERROR_SYNTAX,
6508                  "Parameter ENTITY without Public ID is not rejected");
6509 }
6510 END_TEST
6511 
START_TEST(test_bad_entity_4)6512 START_TEST(test_bad_entity_4) {
6513   const char *text = "<!DOCTYPE doc [\n"
6514                      "  <!ENTITY % foo SYSTEM>\n"
6515                      "]>\n"
6516                      "<doc/>";
6517   expect_failure(text, XML_ERROR_SYNTAX,
6518                  "Parameter ENTITY without Public ID is not rejected");
6519 }
6520 END_TEST
6521 
START_TEST(test_bad_notation)6522 START_TEST(test_bad_notation) {
6523   const char *text = "<!DOCTYPE doc [\n"
6524                      "  <!NOTATION n SYSTEM>\n"
6525                      "]>\n"
6526                      "<doc/>";
6527   expect_failure(text, XML_ERROR_SYNTAX,
6528                  "Notation without System ID is not rejected");
6529 }
6530 END_TEST
6531 
6532 /* Test for issue #11, wrongly suppressed default handler */
6533 typedef struct default_check {
6534   const XML_Char *expected;
6535   const int expectedLen;
6536   XML_Bool seen;
6537 } DefaultCheck;
6538 
6539 static void XMLCALL
checking_default_handler(void * userData,const XML_Char * s,int len)6540 checking_default_handler(void *userData, const XML_Char *s, int len) {
6541   DefaultCheck *data = (DefaultCheck *)userData;
6542   int i;
6543 
6544   for (i = 0; data[i].expected != NULL; i++) {
6545     if (data[i].expectedLen == len
6546         && ! memcmp(data[i].expected, s, len * sizeof(XML_Char))) {
6547       data[i].seen = XML_TRUE;
6548       break;
6549     }
6550   }
6551 }
6552 
START_TEST(test_default_doctype_handler)6553 START_TEST(test_default_doctype_handler) {
6554   const char *text = "<!DOCTYPE doc PUBLIC 'pubname' 'test.dtd' [\n"
6555                      "  <!ENTITY foo 'bar'>\n"
6556                      "]>\n"
6557                      "<doc>&foo;</doc>";
6558   DefaultCheck test_data[] = {{XCS("'pubname'"), 9, XML_FALSE},
6559                               {XCS("'test.dtd'"), 10, XML_FALSE},
6560                               {NULL, 0, XML_FALSE}};
6561   int i;
6562 
6563   XML_SetUserData(g_parser, &test_data);
6564   XML_SetDefaultHandler(g_parser, checking_default_handler);
6565   XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
6566   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6567       == XML_STATUS_ERROR)
6568     xml_failure(g_parser);
6569   for (i = 0; test_data[i].expected != NULL; i++)
6570     if (! test_data[i].seen)
6571       fail("Default handler not run for public !DOCTYPE");
6572 }
6573 END_TEST
6574 
START_TEST(test_empty_element_abort)6575 START_TEST(test_empty_element_abort) {
6576   const char *text = "<abort/>";
6577 
6578   XML_SetStartElementHandler(g_parser, start_element_suspender);
6579   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6580       != XML_STATUS_ERROR)
6581     fail("Expected to error on abort");
6582 }
6583 END_TEST
6584 
6585 /*
6586  * Namespaces tests.
6587  */
6588 
6589 static void
namespace_setup(void)6590 namespace_setup(void) {
6591   g_parser = XML_ParserCreateNS(NULL, XCS(' '));
6592   if (g_parser == NULL)
6593     fail("Parser not created.");
6594 }
6595 
6596 static void
namespace_teardown(void)6597 namespace_teardown(void) {
6598   basic_teardown();
6599 }
6600 
6601 /* Check that an element name and attribute name match the expected values.
6602    The expected values are passed as an array reference of string pointers
6603    provided as the userData argument; the first is the expected
6604    element name, and the second is the expected attribute name.
6605 */
6606 static int triplet_start_flag = XML_FALSE;
6607 static int triplet_end_flag = XML_FALSE;
6608 
6609 static void XMLCALL
triplet_start_checker(void * userData,const XML_Char * name,const XML_Char ** atts)6610 triplet_start_checker(void *userData, const XML_Char *name,
6611                       const XML_Char **atts) {
6612   XML_Char **elemstr = (XML_Char **)userData;
6613   char buffer[1024];
6614   if (xcstrcmp(elemstr[0], name) != 0) {
6615     sprintf(buffer, "unexpected start string: '%" XML_FMT_STR "'", name);
6616     fail(buffer);
6617   }
6618   if (xcstrcmp(elemstr[1], atts[0]) != 0) {
6619     sprintf(buffer, "unexpected attribute string: '%" XML_FMT_STR "'", atts[0]);
6620     fail(buffer);
6621   }
6622   triplet_start_flag = XML_TRUE;
6623 }
6624 
6625 /* Check that the element name passed to the end-element handler matches
6626    the expected value.  The expected value is passed as the first element
6627    in an array of strings passed as the userData argument.
6628 */
6629 static void XMLCALL
triplet_end_checker(void * userData,const XML_Char * name)6630 triplet_end_checker(void *userData, const XML_Char *name) {
6631   XML_Char **elemstr = (XML_Char **)userData;
6632   if (xcstrcmp(elemstr[0], name) != 0) {
6633     char buffer[1024];
6634     sprintf(buffer, "unexpected end string: '%" XML_FMT_STR "'", name);
6635     fail(buffer);
6636   }
6637   triplet_end_flag = XML_TRUE;
6638 }
6639 
START_TEST(test_return_ns_triplet)6640 START_TEST(test_return_ns_triplet) {
6641   const char *text = "<foo:e xmlns:foo='http://example.org/' bar:a='12'\n"
6642                      "       xmlns:bar='http://example.org/'>";
6643   const char *epilog = "</foo:e>";
6644   const XML_Char *elemstr[]
6645       = {XCS("http://example.org/ e foo"), XCS("http://example.org/ a bar")};
6646   XML_SetReturnNSTriplet(g_parser, XML_TRUE);
6647   XML_SetUserData(g_parser, (void *)elemstr);
6648   XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
6649   XML_SetNamespaceDeclHandler(g_parser, dummy_start_namespace_decl_handler,
6650                               dummy_end_namespace_decl_handler);
6651   triplet_start_flag = XML_FALSE;
6652   triplet_end_flag = XML_FALSE;
6653   dummy_handler_flags = 0;
6654   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
6655       == XML_STATUS_ERROR)
6656     xml_failure(g_parser);
6657   if (! triplet_start_flag)
6658     fail("triplet_start_checker not invoked");
6659   /* Check that unsetting "return triplets" fails while still parsing */
6660   XML_SetReturnNSTriplet(g_parser, XML_FALSE);
6661   if (_XML_Parse_SINGLE_BYTES(g_parser, epilog, (int)strlen(epilog), XML_TRUE)
6662       == XML_STATUS_ERROR)
6663     xml_failure(g_parser);
6664   if (! triplet_end_flag)
6665     fail("triplet_end_checker not invoked");
6666   if (dummy_handler_flags
6667       != (DUMMY_START_NS_DECL_HANDLER_FLAG | DUMMY_END_NS_DECL_HANDLER_FLAG))
6668     fail("Namespace handlers not called");
6669 }
6670 END_TEST
6671 
6672 static void XMLCALL
overwrite_start_checker(void * userData,const XML_Char * name,const XML_Char ** atts)6673 overwrite_start_checker(void *userData, const XML_Char *name,
6674                         const XML_Char **atts) {
6675   CharData *storage = (CharData *)userData;
6676   CharData_AppendXMLChars(storage, XCS("start "), 6);
6677   CharData_AppendXMLChars(storage, name, -1);
6678   while (*atts != NULL) {
6679     CharData_AppendXMLChars(storage, XCS("\nattribute "), 11);
6680     CharData_AppendXMLChars(storage, *atts, -1);
6681     atts += 2;
6682   }
6683   CharData_AppendXMLChars(storage, XCS("\n"), 1);
6684 }
6685 
6686 static void XMLCALL
overwrite_end_checker(void * userData,const XML_Char * name)6687 overwrite_end_checker(void *userData, const XML_Char *name) {
6688   CharData *storage = (CharData *)userData;
6689   CharData_AppendXMLChars(storage, XCS("end "), 4);
6690   CharData_AppendXMLChars(storage, name, -1);
6691   CharData_AppendXMLChars(storage, XCS("\n"), 1);
6692 }
6693 
6694 static void
run_ns_tagname_overwrite_test(const char * text,const XML_Char * result)6695 run_ns_tagname_overwrite_test(const char *text, const XML_Char *result) {
6696   CharData storage;
6697   CharData_Init(&storage);
6698   XML_SetUserData(g_parser, &storage);
6699   XML_SetElementHandler(g_parser, overwrite_start_checker,
6700                         overwrite_end_checker);
6701   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6702       == XML_STATUS_ERROR)
6703     xml_failure(g_parser);
6704   CharData_CheckXMLChars(&storage, result);
6705 }
6706 
6707 /* Regression test for SF bug #566334. */
START_TEST(test_ns_tagname_overwrite)6708 START_TEST(test_ns_tagname_overwrite) {
6709   const char *text = "<n:e xmlns:n='http://example.org/'>\n"
6710                      "  <n:f n:attr='foo'/>\n"
6711                      "  <n:g n:attr2='bar'/>\n"
6712                      "</n:e>";
6713   const XML_Char *result = XCS("start http://example.org/ e\n")
6714       XCS("start http://example.org/ f\n")
6715           XCS("attribute http://example.org/ attr\n")
6716               XCS("end http://example.org/ f\n")
6717                   XCS("start http://example.org/ g\n")
6718                       XCS("attribute http://example.org/ attr2\n")
6719                           XCS("end http://example.org/ g\n")
6720                               XCS("end http://example.org/ e\n");
6721   run_ns_tagname_overwrite_test(text, result);
6722 }
6723 END_TEST
6724 
6725 /* Regression test for SF bug #566334. */
START_TEST(test_ns_tagname_overwrite_triplet)6726 START_TEST(test_ns_tagname_overwrite_triplet) {
6727   const char *text = "<n:e xmlns:n='http://example.org/'>\n"
6728                      "  <n:f n:attr='foo'/>\n"
6729                      "  <n:g n:attr2='bar'/>\n"
6730                      "</n:e>";
6731   const XML_Char *result = XCS("start http://example.org/ e n\n")
6732       XCS("start http://example.org/ f n\n")
6733           XCS("attribute http://example.org/ attr n\n")
6734               XCS("end http://example.org/ f n\n")
6735                   XCS("start http://example.org/ g n\n")
6736                       XCS("attribute http://example.org/ attr2 n\n")
6737                           XCS("end http://example.org/ g n\n")
6738                               XCS("end http://example.org/ e n\n");
6739   XML_SetReturnNSTriplet(g_parser, XML_TRUE);
6740   run_ns_tagname_overwrite_test(text, result);
6741 }
6742 END_TEST
6743 
6744 /* Regression test for SF bug #620343. */
6745 static void XMLCALL
start_element_fail(void * userData,const XML_Char * name,const XML_Char ** atts)6746 start_element_fail(void *userData, const XML_Char *name,
6747                    const XML_Char **atts) {
6748   UNUSED_P(userData);
6749   UNUSED_P(name);
6750   UNUSED_P(atts);
6751 
6752   /* We should never get here. */
6753   fail("should never reach start_element_fail()");
6754 }
6755 
6756 static void XMLCALL
start_ns_clearing_start_element(void * userData,const XML_Char * prefix,const XML_Char * uri)6757 start_ns_clearing_start_element(void *userData, const XML_Char *prefix,
6758                                 const XML_Char *uri) {
6759   UNUSED_P(prefix);
6760   UNUSED_P(uri);
6761   XML_SetStartElementHandler((XML_Parser)userData, NULL);
6762 }
6763 
START_TEST(test_start_ns_clears_start_element)6764 START_TEST(test_start_ns_clears_start_element) {
6765   /* This needs to use separate start/end tags; using the empty tag
6766      syntax doesn't cause the problematic path through Expat to be
6767      taken.
6768   */
6769   const char *text = "<e xmlns='http://example.org/'></e>";
6770 
6771   XML_SetStartElementHandler(g_parser, start_element_fail);
6772   XML_SetStartNamespaceDeclHandler(g_parser, start_ns_clearing_start_element);
6773   XML_SetEndNamespaceDeclHandler(g_parser, dummy_end_namespace_decl_handler);
6774   XML_UseParserAsHandlerArg(g_parser);
6775   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6776       == XML_STATUS_ERROR)
6777     xml_failure(g_parser);
6778 }
6779 END_TEST
6780 
6781 /* Regression test for SF bug #616863. */
6782 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)6783 external_entity_handler(XML_Parser parser, const XML_Char *context,
6784                         const XML_Char *base, const XML_Char *systemId,
6785                         const XML_Char *publicId) {
6786   intptr_t callno = 1 + (intptr_t)XML_GetUserData(parser);
6787   const char *text;
6788   XML_Parser p2;
6789 
6790   UNUSED_P(base);
6791   UNUSED_P(systemId);
6792   UNUSED_P(publicId);
6793   if (callno == 1)
6794     text = ("<!ELEMENT doc (e+)>\n"
6795             "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
6796             "<!ELEMENT e EMPTY>\n");
6797   else
6798     text = ("<?xml version='1.0' encoding='us-ascii'?>"
6799             "<e/>");
6800 
6801   XML_SetUserData(parser, (void *)callno);
6802   p2 = XML_ExternalEntityParserCreate(parser, context, NULL);
6803   if (_XML_Parse_SINGLE_BYTES(p2, text, (int)strlen(text), XML_TRUE)
6804       == XML_STATUS_ERROR) {
6805     xml_failure(p2);
6806     return XML_STATUS_ERROR;
6807   }
6808   XML_ParserFree(p2);
6809   return XML_STATUS_OK;
6810 }
6811 
START_TEST(test_default_ns_from_ext_subset_and_ext_ge)6812 START_TEST(test_default_ns_from_ext_subset_and_ext_ge) {
6813   const char *text = "<?xml version='1.0'?>\n"
6814                      "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n"
6815                      "  <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n"
6816                      "]>\n"
6817                      "<doc xmlns='http://example.org/ns1'>\n"
6818                      "&en;\n"
6819                      "</doc>";
6820 
6821   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6822   XML_SetExternalEntityRefHandler(g_parser, external_entity_handler);
6823   /* We actually need to set this handler to tickle this bug. */
6824   XML_SetStartElementHandler(g_parser, dummy_start_element);
6825   XML_SetUserData(g_parser, NULL);
6826   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6827       == XML_STATUS_ERROR)
6828     xml_failure(g_parser);
6829 }
6830 END_TEST
6831 
6832 /* Regression test #1 for SF bug #673791. */
START_TEST(test_ns_prefix_with_empty_uri_1)6833 START_TEST(test_ns_prefix_with_empty_uri_1) {
6834   const char *text = "<doc xmlns:prefix='http://example.org/'>\n"
6835                      "  <e xmlns:prefix=''/>\n"
6836                      "</doc>";
6837 
6838   expect_failure(text, XML_ERROR_UNDECLARING_PREFIX,
6839                  "Did not report re-setting namespace"
6840                  " URI with prefix to ''.");
6841 }
6842 END_TEST
6843 
6844 /* Regression test #2 for SF bug #673791. */
START_TEST(test_ns_prefix_with_empty_uri_2)6845 START_TEST(test_ns_prefix_with_empty_uri_2) {
6846   const char *text = "<?xml version='1.0'?>\n"
6847                      "<docelem xmlns:pre=''/>";
6848 
6849   expect_failure(text, XML_ERROR_UNDECLARING_PREFIX,
6850                  "Did not report setting namespace URI with prefix to ''.");
6851 }
6852 END_TEST
6853 
6854 /* Regression test #3 for SF bug #673791. */
START_TEST(test_ns_prefix_with_empty_uri_3)6855 START_TEST(test_ns_prefix_with_empty_uri_3) {
6856   const char *text = "<!DOCTYPE doc [\n"
6857                      "  <!ELEMENT doc EMPTY>\n"
6858                      "  <!ATTLIST doc\n"
6859                      "    xmlns:prefix CDATA ''>\n"
6860                      "]>\n"
6861                      "<doc/>";
6862 
6863   expect_failure(text, XML_ERROR_UNDECLARING_PREFIX,
6864                  "Didn't report attr default setting NS w/ prefix to ''.");
6865 }
6866 END_TEST
6867 
6868 /* Regression test #4 for SF bug #673791. */
START_TEST(test_ns_prefix_with_empty_uri_4)6869 START_TEST(test_ns_prefix_with_empty_uri_4) {
6870   const char *text = "<!DOCTYPE doc [\n"
6871                      "  <!ELEMENT prefix:doc EMPTY>\n"
6872                      "  <!ATTLIST prefix:doc\n"
6873                      "    xmlns:prefix CDATA 'http://example.org/'>\n"
6874                      "]>\n"
6875                      "<prefix:doc/>";
6876   /* Packaged info expected by the end element handler;
6877      the weird structuring lets us re-use the triplet_end_checker()
6878      function also used for another test. */
6879   const XML_Char *elemstr[] = {XCS("http://example.org/ doc prefix")};
6880   XML_SetReturnNSTriplet(g_parser, XML_TRUE);
6881   XML_SetUserData(g_parser, (void *)elemstr);
6882   XML_SetEndElementHandler(g_parser, triplet_end_checker);
6883   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6884       == XML_STATUS_ERROR)
6885     xml_failure(g_parser);
6886 }
6887 END_TEST
6888 
6889 /* Test with non-xmlns prefix */
START_TEST(test_ns_unbound_prefix)6890 START_TEST(test_ns_unbound_prefix) {
6891   const char *text = "<!DOCTYPE doc [\n"
6892                      "  <!ELEMENT prefix:doc EMPTY>\n"
6893                      "  <!ATTLIST prefix:doc\n"
6894                      "    notxmlns:prefix CDATA 'http://example.org/'>\n"
6895                      "]>\n"
6896                      "<prefix:doc/>";
6897 
6898   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6899       != XML_STATUS_ERROR)
6900     fail("Unbound prefix incorrectly passed");
6901   if (XML_GetErrorCode(g_parser) != XML_ERROR_UNBOUND_PREFIX)
6902     xml_failure(g_parser);
6903 }
6904 END_TEST
6905 
START_TEST(test_ns_default_with_empty_uri)6906 START_TEST(test_ns_default_with_empty_uri) {
6907   const char *text = "<doc xmlns='http://example.org/'>\n"
6908                      "  <e xmlns=''/>\n"
6909                      "</doc>";
6910   /* Add some handlers to exercise extra code paths */
6911   XML_SetStartNamespaceDeclHandler(g_parser,
6912                                    dummy_start_namespace_decl_handler);
6913   XML_SetEndNamespaceDeclHandler(g_parser, dummy_end_namespace_decl_handler);
6914   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6915       == XML_STATUS_ERROR)
6916     xml_failure(g_parser);
6917 }
6918 END_TEST
6919 
6920 /* Regression test for SF bug #692964: two prefixes for one namespace. */
START_TEST(test_ns_duplicate_attrs_diff_prefixes)6921 START_TEST(test_ns_duplicate_attrs_diff_prefixes) {
6922   const char *text = "<doc xmlns:a='http://example.org/a'\n"
6923                      "     xmlns:b='http://example.org/a'\n"
6924                      "     a:a='v' b:a='v' />";
6925   expect_failure(text, XML_ERROR_DUPLICATE_ATTRIBUTE,
6926                  "did not report multiple attributes with same URI+name");
6927 }
6928 END_TEST
6929 
START_TEST(test_ns_duplicate_hashes)6930 START_TEST(test_ns_duplicate_hashes) {
6931   /* The hash of an attribute is calculated as the hash of its URI
6932    * concatenated with a space followed by its name (after the
6933    * colon).  We wish to generate attributes with the same hash
6934    * value modulo the attribute table size so that we can check that
6935    * the attribute hash table works correctly.  The attribute hash
6936    * table size will be the smallest power of two greater than the
6937    * number of attributes, but at least eight.  There is
6938    * unfortunately no programmatic way of getting the hash or the
6939    * table size at user level, but the test code coverage percentage
6940    * will drop if the hashes cease to point to the same row.
6941    *
6942    * The cunning plan is to have few enough attributes to have a
6943    * reliable table size of 8, and have the single letter attribute
6944    * names be 8 characters apart, producing a hash which will be the
6945    * same modulo 8.
6946    */
6947   const char *text = "<doc xmlns:a='http://example.org/a'\n"
6948                      "     a:a='v' a:i='w' />";
6949   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6950       == XML_STATUS_ERROR)
6951     xml_failure(g_parser);
6952 }
6953 END_TEST
6954 
6955 /* Regression test for SF bug #695401: unbound prefix. */
START_TEST(test_ns_unbound_prefix_on_attribute)6956 START_TEST(test_ns_unbound_prefix_on_attribute) {
6957   const char *text = "<doc a:attr=''/>";
6958   expect_failure(text, XML_ERROR_UNBOUND_PREFIX,
6959                  "did not report unbound prefix on attribute");
6960 }
6961 END_TEST
6962 
6963 /* Regression test for SF bug #695401: unbound prefix. */
START_TEST(test_ns_unbound_prefix_on_element)6964 START_TEST(test_ns_unbound_prefix_on_element) {
6965   const char *text = "<a:doc/>";
6966   expect_failure(text, XML_ERROR_UNBOUND_PREFIX,
6967                  "did not report unbound prefix on element");
6968 }
6969 END_TEST
6970 
6971 /* Test that the parsing status is correctly reset by XML_ParserReset().
6972  * We usE test_return_ns_triplet() for our example parse to improve
6973  * coverage of tidying up code executed.
6974  */
START_TEST(test_ns_parser_reset)6975 START_TEST(test_ns_parser_reset) {
6976   XML_ParsingStatus status;
6977 
6978   XML_GetParsingStatus(g_parser, &status);
6979   if (status.parsing != XML_INITIALIZED)
6980     fail("parsing status doesn't start INITIALIZED");
6981   test_return_ns_triplet();
6982   XML_GetParsingStatus(g_parser, &status);
6983   if (status.parsing != XML_FINISHED)
6984     fail("parsing status doesn't end FINISHED");
6985   XML_ParserReset(g_parser, NULL);
6986   XML_GetParsingStatus(g_parser, &status);
6987   if (status.parsing != XML_INITIALIZED)
6988     fail("parsing status doesn't reset to INITIALIZED");
6989 }
6990 END_TEST
6991 
6992 /* Test that long element names with namespaces are handled correctly */
START_TEST(test_ns_long_element)6993 START_TEST(test_ns_long_element) {
6994   const char *text
6995       = "<foo:thisisalongenoughelementnametotriggerareallocation\n"
6996         " xmlns:foo='http://example.org/' bar:a='12'\n"
6997         " xmlns:bar='http://example.org/'>"
6998         "</foo:thisisalongenoughelementnametotriggerareallocation>";
6999   const XML_Char *elemstr[]
7000       = {XCS("http://example.org/")
7001              XCS(" thisisalongenoughelementnametotriggerareallocation foo"),
7002          XCS("http://example.org/ a bar")};
7003 
7004   XML_SetReturnNSTriplet(g_parser, XML_TRUE);
7005   XML_SetUserData(g_parser, (void *)elemstr);
7006   XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
7007   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7008       == XML_STATUS_ERROR)
7009     xml_failure(g_parser);
7010 }
7011 END_TEST
7012 
7013 /* Test mixed population of prefixed and unprefixed attributes */
START_TEST(test_ns_mixed_prefix_atts)7014 START_TEST(test_ns_mixed_prefix_atts) {
7015   const char *text = "<e a='12' bar:b='13'\n"
7016                      " xmlns:bar='http://example.org/'>"
7017                      "</e>";
7018 
7019   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7020       == XML_STATUS_ERROR)
7021     xml_failure(g_parser);
7022 }
7023 END_TEST
7024 
7025 /* Test having a long namespaced element name inside a short one.
7026  * This exercises some internal buffer reallocation that is shared
7027  * across elements with the same namespace URI.
7028  */
START_TEST(test_ns_extend_uri_buffer)7029 START_TEST(test_ns_extend_uri_buffer) {
7030   const char *text = "<foo:e xmlns:foo='http://example.org/'>"
7031                      " <foo:thisisalongenoughnametotriggerallocationaction"
7032                      "   foo:a='12' />"
7033                      "</foo:e>";
7034   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7035       == XML_STATUS_ERROR)
7036     xml_failure(g_parser);
7037 }
7038 END_TEST
7039 
7040 /* Test that xmlns is correctly rejected as an attribute in the xmlns
7041  * namespace, but not in other namespaces
7042  */
START_TEST(test_ns_reserved_attributes)7043 START_TEST(test_ns_reserved_attributes) {
7044   const char *text1
7045       = "<foo:e xmlns:foo='http://example.org/' xmlns:xmlns='12' />";
7046   const char *text2
7047       = "<foo:e xmlns:foo='http://example.org/' foo:xmlns='12' />";
7048   expect_failure(text1, XML_ERROR_RESERVED_PREFIX_XMLNS,
7049                  "xmlns not rejected as an attribute");
7050   XML_ParserReset(g_parser, NULL);
7051   if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
7052       == XML_STATUS_ERROR)
7053     xml_failure(g_parser);
7054 }
7055 END_TEST
7056 
7057 /* Test more reserved attributes */
START_TEST(test_ns_reserved_attributes_2)7058 START_TEST(test_ns_reserved_attributes_2) {
7059   const char *text1 = "<foo:e xmlns:foo='http://example.org/'"
7060                       "  xmlns:xml='http://example.org/' />";
7061   const char *text2
7062       = "<foo:e xmlns:foo='http://www.w3.org/XML/1998/namespace' />";
7063   const char *text3 = "<foo:e xmlns:foo='http://www.w3.org/2000/xmlns/' />";
7064 
7065   expect_failure(text1, XML_ERROR_RESERVED_PREFIX_XML,
7066                  "xml not rejected as an attribute");
7067   XML_ParserReset(g_parser, NULL);
7068   expect_failure(text2, XML_ERROR_RESERVED_NAMESPACE_URI,
7069                  "Use of w3.org URL not faulted");
7070   XML_ParserReset(g_parser, NULL);
7071   expect_failure(text3, XML_ERROR_RESERVED_NAMESPACE_URI,
7072                  "Use of w3.org xmlns URL not faulted");
7073 }
7074 END_TEST
7075 
7076 /* Test string pool handling of namespace names of 2048 characters */
7077 /* Exercises a particular string pool growth path */
START_TEST(test_ns_extremely_long_prefix)7078 START_TEST(test_ns_extremely_long_prefix) {
7079   /* C99 compilers are only required to support 4095-character
7080    * strings, so the following needs to be split in two to be safe
7081    * for all compilers.
7082    */
7083   const char *text1
7084       = "<doc "
7085         /* 64 character on each line */
7086         /* ...gives a total length of 2048 */
7087         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7088         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7089         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7090         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7091         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7092         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7093         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7094         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7095         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7096         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7097         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7098         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7099         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7100         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7101         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7102         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7103         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7104         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7105         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7106         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7107         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7108         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7109         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7110         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7111         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7112         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7113         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7114         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7115         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7116         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7117         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7118         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7119         ":a='12'";
7120   const char *text2
7121       = " xmlns:"
7122         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7123         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7124         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7125         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7126         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7127         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7128         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7129         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7130         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7131         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7132         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7133         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7134         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7135         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7136         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7137         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7138         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7139         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7140         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7141         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7142         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7143         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7144         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7145         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7146         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7147         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7148         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7149         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7150         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7151         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7152         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7153         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7154         "='foo'\n>"
7155         "</doc>";
7156 
7157   if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
7158       == XML_STATUS_ERROR)
7159     xml_failure(g_parser);
7160   if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
7161       == XML_STATUS_ERROR)
7162     xml_failure(g_parser);
7163 }
7164 END_TEST
7165 
7166 /* Test unknown encoding handlers in namespace setup */
START_TEST(test_ns_unknown_encoding_success)7167 START_TEST(test_ns_unknown_encoding_success) {
7168   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
7169                      "<foo:e xmlns:foo='http://example.org/'>Hi</foo:e>";
7170 
7171   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
7172   run_character_check(text, XCS("Hi"));
7173 }
7174 END_TEST
7175 
7176 /* Test that too many colons are rejected */
START_TEST(test_ns_double_colon)7177 START_TEST(test_ns_double_colon) {
7178   const char *text = "<foo:e xmlns:foo='http://example.org/' foo:a:b='bar' />";
7179   const enum XML_Status status
7180       = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE);
7181 #ifdef XML_NS
7182   if ((status == XML_STATUS_OK)
7183       || (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)) {
7184     fail("Double colon in attribute name not faulted"
7185          " (despite active namespace support)");
7186   }
7187 #else
7188   if (status != XML_STATUS_OK) {
7189     fail("Double colon in attribute name faulted"
7190          " (despite inactive namespace support");
7191   }
7192 #endif
7193 }
7194 END_TEST
7195 
START_TEST(test_ns_double_colon_element)7196 START_TEST(test_ns_double_colon_element) {
7197   const char *text = "<foo:bar:e xmlns:foo='http://example.org/' />";
7198   const enum XML_Status status
7199       = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE);
7200 #ifdef XML_NS
7201   if ((status == XML_STATUS_OK)
7202       || (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)) {
7203     fail("Double colon in element name not faulted"
7204          " (despite active namespace support)");
7205   }
7206 #else
7207   if (status != XML_STATUS_OK) {
7208     fail("Double colon in element name faulted"
7209          " (despite inactive namespace support");
7210   }
7211 #endif
7212 }
7213 END_TEST
7214 
7215 /* Test that non-name characters after a colon are rejected */
START_TEST(test_ns_bad_attr_leafname)7216 START_TEST(test_ns_bad_attr_leafname) {
7217   const char *text = "<foo:e xmlns:foo='http://example.org/' foo:?ar='baz' />";
7218 
7219   expect_failure(text, XML_ERROR_INVALID_TOKEN,
7220                  "Invalid character in leafname not faulted");
7221 }
7222 END_TEST
7223 
START_TEST(test_ns_bad_element_leafname)7224 START_TEST(test_ns_bad_element_leafname) {
7225   const char *text = "<foo:?oc xmlns:foo='http://example.org/' />";
7226 
7227   expect_failure(text, XML_ERROR_INVALID_TOKEN,
7228                  "Invalid character in element leafname not faulted");
7229 }
7230 END_TEST
7231 
7232 /* Test high-byte-set UTF-16 characters are valid in a leafname */
START_TEST(test_ns_utf16_leafname)7233 START_TEST(test_ns_utf16_leafname) {
7234   const char text[] =
7235       /* <n:e xmlns:n='URI' n:{KHO KHWAI}='a' />
7236        * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
7237        */
7238       "<\0n\0:\0e\0 \0x\0m\0l\0n\0s\0:\0n\0=\0'\0U\0R\0I\0'\0 \0"
7239       "n\0:\0\x04\x0e=\0'\0a\0'\0 \0/\0>\0";
7240   const XML_Char *expected = XCS("a");
7241   CharData storage;
7242 
7243   CharData_Init(&storage);
7244   XML_SetStartElementHandler(g_parser, accumulate_attribute);
7245   XML_SetUserData(g_parser, &storage);
7246   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
7247       == XML_STATUS_ERROR)
7248     xml_failure(g_parser);
7249   CharData_CheckXMLChars(&storage, expected);
7250 }
7251 END_TEST
7252 
START_TEST(test_ns_utf16_element_leafname)7253 START_TEST(test_ns_utf16_element_leafname) {
7254   const char text[] =
7255       /* <n:{KHO KHWAI} xmlns:n='URI'/>
7256        * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
7257        */
7258       "\0<\0n\0:\x0e\x04\0 \0x\0m\0l\0n\0s\0:\0n\0=\0'\0U\0R\0I\0'\0/\0>";
7259 #ifdef XML_UNICODE
7260   const XML_Char *expected = XCS("URI \x0e04");
7261 #else
7262   const XML_Char *expected = XCS("URI \xe0\xb8\x84");
7263 #endif
7264   CharData storage;
7265 
7266   CharData_Init(&storage);
7267   XML_SetStartElementHandler(g_parser, start_element_event_handler);
7268   XML_SetUserData(g_parser, &storage);
7269   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
7270       == XML_STATUS_ERROR)
7271     xml_failure(g_parser);
7272   CharData_CheckXMLChars(&storage, expected);
7273 }
7274 END_TEST
7275 
START_TEST(test_ns_utf16_doctype)7276 START_TEST(test_ns_utf16_doctype) {
7277   const char text[] =
7278       /* <!DOCTYPE foo:{KHO KHWAI} [ <!ENTITY bar 'baz'> ]>\n
7279        * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
7280        */
7281       "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0f\0o\0o\0:\x0e\x04\0 "
7282       "\0[\0 \0<\0!\0E\0N\0T\0I\0T\0Y\0 \0b\0a\0r\0 \0'\0b\0a\0z\0'\0>\0 "
7283       "\0]\0>\0\n"
7284       /* <foo:{KHO KHWAI} xmlns:foo='URI'>&bar;</foo:{KHO KHWAI}> */
7285       "\0<\0f\0o\0o\0:\x0e\x04\0 "
7286       "\0x\0m\0l\0n\0s\0:\0f\0o\0o\0=\0'\0U\0R\0I\0'\0>"
7287       "\0&\0b\0a\0r\0;"
7288       "\0<\0/\0f\0o\0o\0:\x0e\x04\0>";
7289 #ifdef XML_UNICODE
7290   const XML_Char *expected = XCS("URI \x0e04");
7291 #else
7292   const XML_Char *expected = XCS("URI \xe0\xb8\x84");
7293 #endif
7294   CharData storage;
7295 
7296   CharData_Init(&storage);
7297   XML_SetUserData(g_parser, &storage);
7298   XML_SetStartElementHandler(g_parser, start_element_event_handler);
7299   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
7300   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
7301       == XML_STATUS_ERROR)
7302     xml_failure(g_parser);
7303   CharData_CheckXMLChars(&storage, expected);
7304 }
7305 END_TEST
7306 
START_TEST(test_ns_invalid_doctype)7307 START_TEST(test_ns_invalid_doctype) {
7308   const char *text = "<!DOCTYPE foo:!bad [ <!ENTITY bar 'baz' ]>\n"
7309                      "<foo:!bad>&bar;</foo:!bad>";
7310 
7311   expect_failure(text, XML_ERROR_INVALID_TOKEN,
7312                  "Invalid character in document local name not faulted");
7313 }
7314 END_TEST
7315 
START_TEST(test_ns_double_colon_doctype)7316 START_TEST(test_ns_double_colon_doctype) {
7317   const char *text = "<!DOCTYPE foo:a:doc [ <!ENTITY bar 'baz' ]>\n"
7318                      "<foo:a:doc>&bar;</foo:a:doc>";
7319 
7320   expect_failure(text, XML_ERROR_SYNTAX,
7321                  "Double colon in document name not faulted");
7322 }
7323 END_TEST
7324 
7325 /* Control variable; the number of times duff_allocator() will successfully
7326  * allocate */
7327 #define ALLOC_ALWAYS_SUCCEED (-1)
7328 #define REALLOC_ALWAYS_SUCCEED (-1)
7329 
7330 static intptr_t allocation_count = ALLOC_ALWAYS_SUCCEED;
7331 static intptr_t reallocation_count = REALLOC_ALWAYS_SUCCEED;
7332 
7333 /* Crocked allocator for allocation failure tests */
7334 static void *
duff_allocator(size_t size)7335 duff_allocator(size_t size) {
7336   if (allocation_count == 0)
7337     return NULL;
7338   if (allocation_count != ALLOC_ALWAYS_SUCCEED)
7339     allocation_count--;
7340   return malloc(size);
7341 }
7342 
7343 /* Crocked reallocator for allocation failure tests */
7344 static void *
duff_reallocator(void * ptr,size_t size)7345 duff_reallocator(void *ptr, size_t size) {
7346   if (reallocation_count == 0)
7347     return NULL;
7348   if (reallocation_count != REALLOC_ALWAYS_SUCCEED)
7349     reallocation_count--;
7350   return realloc(ptr, size);
7351 }
7352 
7353 /* Test that a failure to allocate the parser structure fails gracefully */
START_TEST(test_misc_alloc_create_parser)7354 START_TEST(test_misc_alloc_create_parser) {
7355   XML_Memory_Handling_Suite memsuite = {duff_allocator, realloc, free};
7356   unsigned int i;
7357   const unsigned int max_alloc_count = 10;
7358 
7359   /* Something this simple shouldn't need more than 10 allocations */
7360   for (i = 0; i < max_alloc_count; i++) {
7361     allocation_count = i;
7362     g_parser = XML_ParserCreate_MM(NULL, &memsuite, NULL);
7363     if (g_parser != NULL)
7364       break;
7365   }
7366   if (i == 0)
7367     fail("Parser unexpectedly ignored failing allocator");
7368   else if (i == max_alloc_count)
7369     fail("Parser not created with max allocation count");
7370 }
7371 END_TEST
7372 
7373 /* Test memory allocation failures for a parser with an encoding */
START_TEST(test_misc_alloc_create_parser_with_encoding)7374 START_TEST(test_misc_alloc_create_parser_with_encoding) {
7375   XML_Memory_Handling_Suite memsuite = {duff_allocator, realloc, free};
7376   unsigned int i;
7377   const unsigned int max_alloc_count = 10;
7378 
7379   /* Try several levels of allocation */
7380   for (i = 0; i < max_alloc_count; i++) {
7381     allocation_count = i;
7382     g_parser = XML_ParserCreate_MM(XCS("us-ascii"), &memsuite, NULL);
7383     if (g_parser != NULL)
7384       break;
7385   }
7386   if (i == 0)
7387     fail("Parser ignored failing allocator");
7388   else if (i == max_alloc_count)
7389     fail("Parser not created with max allocation count");
7390 }
7391 END_TEST
7392 
7393 /* Test that freeing a NULL parser doesn't cause an explosion.
7394  * (Not actually tested anywhere else)
7395  */
START_TEST(test_misc_null_parser)7396 START_TEST(test_misc_null_parser) {
7397   XML_ParserFree(NULL);
7398 }
7399 END_TEST
7400 
7401 /* Test that XML_ErrorString rejects out-of-range codes */
START_TEST(test_misc_error_string)7402 START_TEST(test_misc_error_string) {
7403   if (XML_ErrorString((enum XML_Error) - 1) != NULL)
7404     fail("Negative error code not rejected");
7405   if (XML_ErrorString((enum XML_Error)100) != NULL)
7406     fail("Large error code not rejected");
7407 }
7408 END_TEST
7409 
7410 /* Test the version information is consistent */
7411 
7412 /* Since we are working in XML_LChars (potentially 16-bits), we
7413  * can't use the standard C library functions for character
7414  * manipulation and have to roll our own.
7415  */
7416 static int
parse_version(const XML_LChar * version_text,XML_Expat_Version * version_struct)7417 parse_version(const XML_LChar *version_text,
7418               XML_Expat_Version *version_struct) {
7419   if (! version_text)
7420     return XML_FALSE;
7421 
7422   while (*version_text != 0x00) {
7423     if (*version_text >= ASCII_0 && *version_text <= ASCII_9)
7424       break;
7425     version_text++;
7426   }
7427   if (*version_text == 0x00)
7428     return XML_FALSE;
7429 
7430   /* version_struct->major = strtoul(version_text, 10, &version_text) */
7431   version_struct->major = 0;
7432   while (*version_text >= ASCII_0 && *version_text <= ASCII_9) {
7433     version_struct->major
7434         = 10 * version_struct->major + (*version_text++ - ASCII_0);
7435   }
7436   if (*version_text++ != ASCII_PERIOD)
7437     return XML_FALSE;
7438 
7439   /* Now for the minor version number */
7440   version_struct->minor = 0;
7441   while (*version_text >= ASCII_0 && *version_text <= ASCII_9) {
7442     version_struct->minor
7443         = 10 * version_struct->minor + (*version_text++ - ASCII_0);
7444   }
7445   if (*version_text++ != ASCII_PERIOD)
7446     return XML_FALSE;
7447 
7448   /* Finally the micro version number */
7449   version_struct->micro = 0;
7450   while (*version_text >= ASCII_0 && *version_text <= ASCII_9) {
7451     version_struct->micro
7452         = 10 * version_struct->micro + (*version_text++ - ASCII_0);
7453   }
7454   if (*version_text != 0x00)
7455     return XML_FALSE;
7456   return XML_TRUE;
7457 }
7458 
7459 static int
versions_equal(const XML_Expat_Version * first,const XML_Expat_Version * second)7460 versions_equal(const XML_Expat_Version *first,
7461                const XML_Expat_Version *second) {
7462   return (first->major == second->major && first->minor == second->minor
7463           && first->micro == second->micro);
7464 }
7465 
START_TEST(test_misc_version)7466 START_TEST(test_misc_version) {
7467   XML_Expat_Version read_version = XML_ExpatVersionInfo();
7468   /* Silence compiler warning with the following assignment */
7469   XML_Expat_Version parsed_version = {0, 0, 0};
7470   const XML_LChar *version_text = XML_ExpatVersion();
7471 
7472   if (version_text == NULL)
7473     fail("Could not obtain version text");
7474   assert(version_text != NULL);
7475   if (! parse_version(version_text, &parsed_version))
7476     fail("Unable to parse version text");
7477   if (! versions_equal(&read_version, &parsed_version))
7478     fail("Version mismatch");
7479 
7480 #if ! defined(XML_UNICODE) || defined(XML_UNICODE_WCHAR_T)
7481   if (xcstrcmp(version_text, XCS("expat_2.4.1"))) /* needs bump on releases */
7482     fail("XML_*_VERSION in expat.h out of sync?\n");
7483 #else
7484   /* If we have XML_UNICODE defined but not XML_UNICODE_WCHAR_T
7485    * then XML_LChar is defined as char, for some reason.
7486    */
7487   if (strcmp(version_text, "expat_2.2.5")) /* needs bump on releases */
7488     fail("XML_*_VERSION in expat.h out of sync?\n");
7489 #endif /* ! defined(XML_UNICODE) || defined(XML_UNICODE_WCHAR_T) */
7490 }
7491 END_TEST
7492 
7493 /* Test feature information */
START_TEST(test_misc_features)7494 START_TEST(test_misc_features) {
7495   const XML_Feature *features = XML_GetFeatureList();
7496 
7497   /* Prevent problems with double-freeing parsers */
7498   g_parser = NULL;
7499   if (features == NULL) {
7500     fail("Failed to get feature information");
7501   } else {
7502     /* Loop through the features checking what we can */
7503     while (features->feature != XML_FEATURE_END) {
7504       switch (features->feature) {
7505       case XML_FEATURE_SIZEOF_XML_CHAR:
7506         if (features->value != sizeof(XML_Char))
7507           fail("Incorrect size of XML_Char");
7508         break;
7509       case XML_FEATURE_SIZEOF_XML_LCHAR:
7510         if (features->value != sizeof(XML_LChar))
7511           fail("Incorrect size of XML_LChar");
7512         break;
7513       default:
7514         break;
7515       }
7516       features++;
7517     }
7518   }
7519 }
7520 END_TEST
7521 
7522 /* Regression test for GitHub Issue #17: memory leak parsing attribute
7523  * values with mixed bound and unbound namespaces.
7524  */
START_TEST(test_misc_attribute_leak)7525 START_TEST(test_misc_attribute_leak) {
7526   const char *text = "<D xmlns:L=\"D\" l:a='' L:a=''/>";
7527   XML_Memory_Handling_Suite memsuite
7528       = {tracking_malloc, tracking_realloc, tracking_free};
7529 
7530   g_parser = XML_ParserCreate_MM(XCS("UTF-8"), &memsuite, XCS("\n"));
7531   expect_failure(text, XML_ERROR_UNBOUND_PREFIX, "Unbound prefixes not found");
7532   XML_ParserFree(g_parser);
7533   /* Prevent the teardown trying to double free */
7534   g_parser = NULL;
7535 
7536   if (! tracking_report())
7537     fail("Memory leak found");
7538 }
7539 END_TEST
7540 
7541 /* Test parser created for UTF-16LE is successful */
START_TEST(test_misc_utf16le)7542 START_TEST(test_misc_utf16le) {
7543   const char text[] =
7544       /* <?xml version='1.0'?><q>Hi</q> */
7545       "<\0?\0x\0m\0l\0 \0"
7546       "v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0?\0>\0"
7547       "<\0q\0>\0H\0i\0<\0/\0q\0>\0";
7548   const XML_Char *expected = XCS("Hi");
7549   CharData storage;
7550 
7551   g_parser = XML_ParserCreate(XCS("UTF-16LE"));
7552   if (g_parser == NULL)
7553     fail("Parser not created");
7554 
7555   CharData_Init(&storage);
7556   XML_SetUserData(g_parser, &storage);
7557   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
7558   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
7559       == XML_STATUS_ERROR)
7560     xml_failure(g_parser);
7561   CharData_CheckXMLChars(&storage, expected);
7562 }
7563 END_TEST
7564 
7565 typedef struct {
7566   XML_Parser parser;
7567   int deep;
7568 } DataIssue240;
7569 
7570 static void
start_element_issue_240(void * userData,const XML_Char * name,const XML_Char ** atts)7571 start_element_issue_240(void *userData, const XML_Char *name,
7572                         const XML_Char **atts) {
7573   DataIssue240 *mydata = (DataIssue240 *)userData;
7574   UNUSED_P(name);
7575   UNUSED_P(atts);
7576   mydata->deep++;
7577 }
7578 
7579 static void
end_element_issue_240(void * userData,const XML_Char * name)7580 end_element_issue_240(void *userData, const XML_Char *name) {
7581   DataIssue240 *mydata = (DataIssue240 *)userData;
7582 
7583   UNUSED_P(name);
7584   mydata->deep--;
7585   if (mydata->deep == 0) {
7586     XML_StopParser(mydata->parser, 0);
7587   }
7588 }
7589 
START_TEST(test_misc_stop_during_end_handler_issue_240_1)7590 START_TEST(test_misc_stop_during_end_handler_issue_240_1) {
7591   XML_Parser parser;
7592   DataIssue240 *mydata;
7593   enum XML_Status result;
7594   const char *const doc1 = "<doc><e1/><e><foo/></e></doc>";
7595 
7596   parser = XML_ParserCreate(NULL);
7597   XML_SetElementHandler(parser, start_element_issue_240, end_element_issue_240);
7598   mydata = (DataIssue240 *)malloc(sizeof(DataIssue240));
7599   mydata->parser = parser;
7600   mydata->deep = 0;
7601   XML_SetUserData(parser, mydata);
7602 
7603   result = XML_Parse(parser, doc1, (int)strlen(doc1), 1);
7604   XML_ParserFree(parser);
7605   free(mydata);
7606   if (result != XML_STATUS_ERROR)
7607     fail("Stopping the parser did not work as expected");
7608 }
7609 END_TEST
7610 
START_TEST(test_misc_stop_during_end_handler_issue_240_2)7611 START_TEST(test_misc_stop_during_end_handler_issue_240_2) {
7612   XML_Parser parser;
7613   DataIssue240 *mydata;
7614   enum XML_Status result;
7615   const char *const doc2 = "<doc><elem/></doc>";
7616 
7617   parser = XML_ParserCreate(NULL);
7618   XML_SetElementHandler(parser, start_element_issue_240, end_element_issue_240);
7619   mydata = (DataIssue240 *)malloc(sizeof(DataIssue240));
7620   mydata->parser = parser;
7621   mydata->deep = 0;
7622   XML_SetUserData(parser, mydata);
7623 
7624   result = XML_Parse(parser, doc2, (int)strlen(doc2), 1);
7625   XML_ParserFree(parser);
7626   free(mydata);
7627   if (result != XML_STATUS_ERROR)
7628     fail("Stopping the parser did not work as expected");
7629 }
7630 END_TEST
7631 
START_TEST(test_misc_deny_internal_entity_closing_doctype_issue_317)7632 START_TEST(test_misc_deny_internal_entity_closing_doctype_issue_317) {
7633   const char *const inputOne = "<!DOCTYPE d [\n"
7634                                "<!ENTITY % e ']><d/>'>\n"
7635                                "\n"
7636                                "%e;";
7637   const char *const inputTwo = "<!DOCTYPE d [\n"
7638                                "<!ENTITY % e1 ']><d/>'><!ENTITY % e2 '&e1;'>\n"
7639                                "\n"
7640                                "%e2;";
7641   const char *const inputThree = "<!DOCTYPE d [\n"
7642                                  "<!ENTITY % e ']><d'>\n"
7643                                  "\n"
7644                                  "%e;";
7645   const char *const inputIssue317 = "<!DOCTYPE doc [\n"
7646                                     "<!ENTITY % foo ']>\n"
7647                                     "<doc>Hell<oc (#PCDATA)*>'>\n"
7648                                     "%foo;\n"
7649                                     "]>\n"
7650                                     "<doc>Hello, world</dVc>";
7651 
7652   const char *const inputs[] = {inputOne, inputTwo, inputThree, inputIssue317};
7653   size_t inputIndex = 0;
7654 
7655   for (; inputIndex < sizeof(inputs) / sizeof(inputs[0]); inputIndex++) {
7656     XML_Parser parser;
7657     enum XML_Status parseResult;
7658     int setParamEntityResult;
7659     XML_Size lineNumber;
7660     XML_Size columnNumber;
7661     const char *const input = inputs[inputIndex];
7662 
7663     parser = XML_ParserCreate(NULL);
7664     setParamEntityResult
7665         = XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
7666     if (setParamEntityResult != 1)
7667       fail("Failed to set XML_PARAM_ENTITY_PARSING_ALWAYS.");
7668 
7669     parseResult = XML_Parse(parser, input, (int)strlen(input), 0);
7670     if (parseResult != XML_STATUS_ERROR) {
7671       parseResult = XML_Parse(parser, "", 0, 1);
7672       if (parseResult != XML_STATUS_ERROR) {
7673         fail("Parsing was expected to fail but succeeded.");
7674       }
7675     }
7676 
7677     if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN)
7678       fail("Error code does not match XML_ERROR_INVALID_TOKEN");
7679 
7680     lineNumber = XML_GetCurrentLineNumber(parser);
7681     if (lineNumber != 4)
7682       fail("XML_GetCurrentLineNumber does not work as expected.");
7683 
7684     columnNumber = XML_GetCurrentColumnNumber(parser);
7685     if (columnNumber != 0)
7686       fail("XML_GetCurrentColumnNumber does not work as expected.");
7687 
7688     XML_ParserFree(parser);
7689   }
7690 }
7691 END_TEST
7692 
7693 static int XMLCALL
external_entity_parser_create_alloc_fail_handler(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)7694 external_entity_parser_create_alloc_fail_handler(XML_Parser parser,
7695                                                  const XML_Char *context,
7696                                                  const XML_Char *base,
7697                                                  const XML_Char *systemId,
7698                                                  const XML_Char *publicId) {
7699   UNUSED_P(base);
7700   UNUSED_P(systemId);
7701   UNUSED_P(publicId);
7702 
7703   if (context != NULL)
7704     fail("Unexpected non-NULL context");
7705 
7706   // The following number intends to fail the upcoming allocation in line
7707   // "parser->m_protocolEncodingName = copyString(encodingName,
7708   // &(parser->m_mem));" in function parserInit.
7709   allocation_count = 3;
7710 
7711   const XML_Char *const encodingName = XCS("UTF-8"); // needs something non-NULL
7712   const XML_Parser ext_parser
7713       = XML_ExternalEntityParserCreate(parser, context, encodingName);
7714   if (ext_parser != NULL)
7715     fail(
7716         "Call to XML_ExternalEntityParserCreate was expected to fail out-of-memory");
7717 
7718   allocation_count = ALLOC_ALWAYS_SUCCEED;
7719   return XML_STATUS_ERROR;
7720 }
7721 
START_TEST(test_alloc_reset_after_external_entity_parser_create_fail)7722 START_TEST(test_alloc_reset_after_external_entity_parser_create_fail) {
7723   const char *const text = "<!DOCTYPE doc SYSTEM 'foo'><doc/>";
7724 
7725   XML_SetExternalEntityRefHandler(
7726       g_parser, external_entity_parser_create_alloc_fail_handler);
7727   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
7728 
7729   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
7730       != XML_STATUS_ERROR)
7731     fail("Call to parse was expected to fail");
7732 
7733   if (XML_GetErrorCode(g_parser) != XML_ERROR_EXTERNAL_ENTITY_HANDLING)
7734     fail("Call to parse was expected to fail from the external entity handler");
7735 
7736   XML_ParserReset(g_parser, NULL);
7737 }
7738 END_TEST
7739 
7740 static void
alloc_setup(void)7741 alloc_setup(void) {
7742   XML_Memory_Handling_Suite memsuite = {duff_allocator, duff_reallocator, free};
7743 
7744   /* Ensure the parser creation will go through */
7745   allocation_count = ALLOC_ALWAYS_SUCCEED;
7746   reallocation_count = REALLOC_ALWAYS_SUCCEED;
7747   g_parser = XML_ParserCreate_MM(NULL, &memsuite, NULL);
7748   if (g_parser == NULL)
7749     fail("Parser not created");
7750 }
7751 
7752 static void
alloc_teardown(void)7753 alloc_teardown(void) {
7754   basic_teardown();
7755 }
7756 
7757 /* Test the effects of allocation failures on xml declaration processing */
START_TEST(test_alloc_parse_xdecl)7758 START_TEST(test_alloc_parse_xdecl) {
7759   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
7760                      "<doc>Hello, world</doc>";
7761   int i;
7762   const int max_alloc_count = 15;
7763 
7764   for (i = 0; i < max_alloc_count; i++) {
7765     allocation_count = i;
7766     XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler);
7767     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7768         != XML_STATUS_ERROR)
7769       break;
7770     /* Resetting the parser is insufficient, because some memory
7771      * allocations are cached within the parser.  Instead we use
7772      * the teardown and setup routines to ensure that we have the
7773      * right sort of parser back in our hands.
7774      */
7775     alloc_teardown();
7776     alloc_setup();
7777   }
7778   if (i == 0)
7779     fail("Parse succeeded despite failing allocator");
7780   if (i == max_alloc_count)
7781     fail("Parse failed with max allocations");
7782 }
7783 END_TEST
7784 
7785 /* As above, but with an encoding big enough to cause storing the
7786  * version information to expand the string pool being used.
7787  */
7788 static int XMLCALL
long_encoding_handler(void * userData,const XML_Char * encoding,XML_Encoding * info)7789 long_encoding_handler(void *userData, const XML_Char *encoding,
7790                       XML_Encoding *info) {
7791   int i;
7792 
7793   UNUSED_P(userData);
7794   UNUSED_P(encoding);
7795   for (i = 0; i < 256; i++)
7796     info->map[i] = i;
7797   info->data = NULL;
7798   info->convert = NULL;
7799   info->release = NULL;
7800   return XML_STATUS_OK;
7801 }
7802 
START_TEST(test_alloc_parse_xdecl_2)7803 START_TEST(test_alloc_parse_xdecl_2) {
7804   const char *text
7805       = "<?xml version='1.0' encoding='"
7806         /* Each line is 64 characters */
7807         "ThisIsAStupidlyLongEncodingNameIntendedToTriggerPoolGrowth123456"
7808         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7809         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7810         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7811         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7812         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7813         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7814         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7815         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7816         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7817         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7818         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7819         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7820         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7821         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7822         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN"
7823         "'?>"
7824         "<doc>Hello, world</doc>";
7825   int i;
7826   const int max_alloc_count = 20;
7827 
7828   for (i = 0; i < max_alloc_count; i++) {
7829     allocation_count = i;
7830     XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler);
7831     XML_SetUnknownEncodingHandler(g_parser, long_encoding_handler, NULL);
7832     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7833         != XML_STATUS_ERROR)
7834       break;
7835     /* See comment in test_alloc_parse_xdecl() */
7836     alloc_teardown();
7837     alloc_setup();
7838   }
7839   if (i == 0)
7840     fail("Parse succeeded despite failing allocator");
7841   if (i == max_alloc_count)
7842     fail("Parse failed with max allocations");
7843 }
7844 END_TEST
7845 
7846 /* Test the effects of allocation failures on a straightforward parse */
START_TEST(test_alloc_parse_pi)7847 START_TEST(test_alloc_parse_pi) {
7848   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
7849                      "<?pi unknown?>\n"
7850                      "<doc>"
7851                      "Hello, world"
7852                      "</doc>";
7853   int i;
7854   const int max_alloc_count = 15;
7855 
7856   for (i = 0; i < max_alloc_count; i++) {
7857     allocation_count = i;
7858     XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
7859     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7860         != XML_STATUS_ERROR)
7861       break;
7862     /* See comment in test_alloc_parse_xdecl() */
7863     alloc_teardown();
7864     alloc_setup();
7865   }
7866   if (i == 0)
7867     fail("Parse succeeded despite failing allocator");
7868   if (i == max_alloc_count)
7869     fail("Parse failed with max allocations");
7870 }
7871 END_TEST
7872 
START_TEST(test_alloc_parse_pi_2)7873 START_TEST(test_alloc_parse_pi_2) {
7874   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
7875                      "<doc>"
7876                      "Hello, world"
7877                      "<?pi unknown?>\n"
7878                      "</doc>";
7879   int i;
7880   const int max_alloc_count = 15;
7881 
7882   for (i = 0; i < max_alloc_count; i++) {
7883     allocation_count = i;
7884     XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
7885     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7886         != XML_STATUS_ERROR)
7887       break;
7888     /* See comment in test_alloc_parse_xdecl() */
7889     alloc_teardown();
7890     alloc_setup();
7891   }
7892   if (i == 0)
7893     fail("Parse succeeded despite failing allocator");
7894   if (i == max_alloc_count)
7895     fail("Parse failed with max allocations");
7896 }
7897 END_TEST
7898 
START_TEST(test_alloc_parse_pi_3)7899 START_TEST(test_alloc_parse_pi_3) {
7900   const char *text
7901       = "<?"
7902         /* 64 characters per line */
7903         "This processing instruction should be long enough to ensure that"
7904         "it triggers the growth of an internal string pool when the      "
7905         "allocator fails at a cruicial moment FGHIJKLMNOPABCDEFGHIJKLMNOP"
7906         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7907         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7908         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7909         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7910         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7911         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7912         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7913         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7914         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7915         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7916         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7917         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7918         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7919         "Q?><doc/>";
7920   int i;
7921   const int max_alloc_count = 20;
7922 
7923   for (i = 0; i < max_alloc_count; i++) {
7924     allocation_count = i;
7925     XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
7926     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7927         != XML_STATUS_ERROR)
7928       break;
7929     /* See comment in test_alloc_parse_xdecl() */
7930     alloc_teardown();
7931     alloc_setup();
7932   }
7933   if (i == 0)
7934     fail("Parse succeeded despite failing allocator");
7935   if (i == max_alloc_count)
7936     fail("Parse failed with max allocations");
7937 }
7938 END_TEST
7939 
START_TEST(test_alloc_parse_comment)7940 START_TEST(test_alloc_parse_comment) {
7941   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
7942                      "<!-- Test parsing this comment -->"
7943                      "<doc>Hi</doc>";
7944   int i;
7945   const int max_alloc_count = 15;
7946 
7947   for (i = 0; i < max_alloc_count; i++) {
7948     allocation_count = i;
7949     XML_SetCommentHandler(g_parser, dummy_comment_handler);
7950     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7951         != XML_STATUS_ERROR)
7952       break;
7953     /* See comment in test_alloc_parse_xdecl() */
7954     alloc_teardown();
7955     alloc_setup();
7956   }
7957   if (i == 0)
7958     fail("Parse succeeded despite failing allocator");
7959   if (i == max_alloc_count)
7960     fail("Parse failed with max allocations");
7961 }
7962 END_TEST
7963 
START_TEST(test_alloc_parse_comment_2)7964 START_TEST(test_alloc_parse_comment_2) {
7965   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
7966                      "<doc>"
7967                      "Hello, world"
7968                      "<!-- Parse this comment too -->"
7969                      "</doc>";
7970   int i;
7971   const int max_alloc_count = 15;
7972 
7973   for (i = 0; i < max_alloc_count; i++) {
7974     allocation_count = i;
7975     XML_SetCommentHandler(g_parser, dummy_comment_handler);
7976     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7977         != XML_STATUS_ERROR)
7978       break;
7979     /* See comment in test_alloc_parse_xdecl() */
7980     alloc_teardown();
7981     alloc_setup();
7982   }
7983   if (i == 0)
7984     fail("Parse succeeded despite failing allocator");
7985   if (i == max_alloc_count)
7986     fail("Parse failed with max allocations");
7987 }
7988 END_TEST
7989 
7990 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)7991 external_entity_duff_loader(XML_Parser parser, const XML_Char *context,
7992                             const XML_Char *base, const XML_Char *systemId,
7993                             const XML_Char *publicId) {
7994   XML_Parser new_parser;
7995   unsigned int i;
7996   const unsigned int max_alloc_count = 10;
7997 
7998   UNUSED_P(base);
7999   UNUSED_P(systemId);
8000   UNUSED_P(publicId);
8001   /* Try a few different allocation levels */
8002   for (i = 0; i < max_alloc_count; i++) {
8003     allocation_count = i;
8004     new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8005     if (new_parser != NULL) {
8006       XML_ParserFree(new_parser);
8007       break;
8008     }
8009   }
8010   if (i == 0)
8011     fail("External parser creation ignored failing allocator");
8012   else if (i == max_alloc_count)
8013     fail("Extern parser not created with max allocation count");
8014 
8015   /* Make sure other random allocation doesn't now fail */
8016   allocation_count = ALLOC_ALWAYS_SUCCEED;
8017 
8018   /* Make sure the failure code path is executed too */
8019   return XML_STATUS_ERROR;
8020 }
8021 
8022 /* Test that external parser creation running out of memory is
8023  * correctly reported.  Based on the external entity test cases.
8024  */
START_TEST(test_alloc_create_external_parser)8025 START_TEST(test_alloc_create_external_parser) {
8026   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
8027                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
8028                      "<doc>&entity;</doc>";
8029   char foo_text[] = "<!ELEMENT doc (#PCDATA)*>";
8030 
8031   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8032   XML_SetUserData(g_parser, foo_text);
8033   XML_SetExternalEntityRefHandler(g_parser, external_entity_duff_loader);
8034   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8035       != XML_STATUS_ERROR) {
8036     fail("External parser allocator returned success incorrectly");
8037   }
8038 }
8039 END_TEST
8040 
8041 /* More external parser memory allocation testing */
START_TEST(test_alloc_run_external_parser)8042 START_TEST(test_alloc_run_external_parser) {
8043   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
8044                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
8045                      "<doc>&entity;</doc>";
8046   char foo_text[] = "<!ELEMENT doc (#PCDATA)*>";
8047   unsigned int i;
8048   const unsigned int max_alloc_count = 15;
8049 
8050   for (i = 0; i < max_alloc_count; i++) {
8051     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8052     XML_SetUserData(g_parser, foo_text);
8053     XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader);
8054     allocation_count = i;
8055     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8056         != XML_STATUS_ERROR)
8057       break;
8058     /* See comment in test_alloc_parse_xdecl() */
8059     alloc_teardown();
8060     alloc_setup();
8061   }
8062   if (i == 0)
8063     fail("Parsing ignored failing allocator");
8064   else if (i == max_alloc_count)
8065     fail("Parsing failed with allocation count 10");
8066 }
8067 END_TEST
8068 
8069 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)8070 external_entity_dbl_handler(XML_Parser parser, const XML_Char *context,
8071                             const XML_Char *base, const XML_Char *systemId,
8072                             const XML_Char *publicId) {
8073   intptr_t callno = (intptr_t)XML_GetUserData(parser);
8074   const char *text;
8075   XML_Parser new_parser;
8076   int i;
8077   const int max_alloc_count = 20;
8078 
8079   UNUSED_P(base);
8080   UNUSED_P(systemId);
8081   UNUSED_P(publicId);
8082   if (callno == 0) {
8083     /* First time through, check how many calls to malloc occur */
8084     text = ("<!ELEMENT doc (e+)>\n"
8085             "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
8086             "<!ELEMENT e EMPTY>\n");
8087     allocation_count = 10000;
8088     new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8089     if (new_parser == NULL) {
8090       fail("Unable to allocate first external parser");
8091       return XML_STATUS_ERROR;
8092     }
8093     /* Stash the number of calls in the user data */
8094     XML_SetUserData(parser, (void *)(intptr_t)(10000 - allocation_count));
8095   } else {
8096     text = ("<?xml version='1.0' encoding='us-ascii'?>"
8097             "<e/>");
8098     /* Try at varying levels to exercise more code paths */
8099     for (i = 0; i < max_alloc_count; i++) {
8100       allocation_count = callno + i;
8101       new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8102       if (new_parser != NULL)
8103         break;
8104     }
8105     if (i == 0) {
8106       fail("Second external parser unexpectedly created");
8107       XML_ParserFree(new_parser);
8108       return XML_STATUS_ERROR;
8109     } else if (i == max_alloc_count) {
8110       fail("Second external parser not created");
8111       return XML_STATUS_ERROR;
8112     }
8113   }
8114 
8115   allocation_count = ALLOC_ALWAYS_SUCCEED;
8116   if (_XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE)
8117       == XML_STATUS_ERROR) {
8118     xml_failure(new_parser);
8119     return XML_STATUS_ERROR;
8120   }
8121   XML_ParserFree(new_parser);
8122   return XML_STATUS_OK;
8123 }
8124 
8125 /* Test that running out of memory in dtdCopy is correctly reported.
8126  * Based on test_default_ns_from_ext_subset_and_ext_ge()
8127  */
START_TEST(test_alloc_dtd_copy_default_atts)8128 START_TEST(test_alloc_dtd_copy_default_atts) {
8129   const char *text = "<?xml version='1.0'?>\n"
8130                      "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n"
8131                      "  <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n"
8132                      "]>\n"
8133                      "<doc xmlns='http://example.org/ns1'>\n"
8134                      "&en;\n"
8135                      "</doc>";
8136 
8137   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8138   XML_SetExternalEntityRefHandler(g_parser, external_entity_dbl_handler);
8139   XML_SetUserData(g_parser, NULL);
8140   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8141       == XML_STATUS_ERROR)
8142     xml_failure(g_parser);
8143 }
8144 END_TEST
8145 
8146 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)8147 external_entity_dbl_handler_2(XML_Parser parser, const XML_Char *context,
8148                               const XML_Char *base, const XML_Char *systemId,
8149                               const XML_Char *publicId) {
8150   intptr_t callno = (intptr_t)XML_GetUserData(parser);
8151   const char *text;
8152   XML_Parser new_parser;
8153   enum XML_Status rv;
8154 
8155   UNUSED_P(base);
8156   UNUSED_P(systemId);
8157   UNUSED_P(publicId);
8158   if (callno == 0) {
8159     /* Try different allocation levels for whole exercise */
8160     text = ("<!ELEMENT doc (e+)>\n"
8161             "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
8162             "<!ELEMENT e EMPTY>\n");
8163     XML_SetUserData(parser, (void *)(intptr_t)1);
8164     new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8165     if (new_parser == NULL)
8166       return XML_STATUS_ERROR;
8167     rv = _XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE);
8168   } else {
8169     /* Just run through once */
8170     text = ("<?xml version='1.0' encoding='us-ascii'?>"
8171             "<e/>");
8172     new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8173     if (new_parser == NULL)
8174       return XML_STATUS_ERROR;
8175     rv = _XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE);
8176   }
8177   XML_ParserFree(new_parser);
8178   if (rv == XML_STATUS_ERROR)
8179     return XML_STATUS_ERROR;
8180   return XML_STATUS_OK;
8181 }
8182 
8183 /* Test more external entity allocation failure paths */
START_TEST(test_alloc_external_entity)8184 START_TEST(test_alloc_external_entity) {
8185   const char *text = "<?xml version='1.0'?>\n"
8186                      "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n"
8187                      "  <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n"
8188                      "]>\n"
8189                      "<doc xmlns='http://example.org/ns1'>\n"
8190                      "&en;\n"
8191                      "</doc>";
8192   int i;
8193   const int alloc_test_max_repeats = 50;
8194 
8195   for (i = 0; i < alloc_test_max_repeats; i++) {
8196     allocation_count = -1;
8197     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8198     XML_SetExternalEntityRefHandler(g_parser, external_entity_dbl_handler_2);
8199     XML_SetUserData(g_parser, NULL);
8200     allocation_count = i;
8201     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8202         == XML_STATUS_OK)
8203       break;
8204     /* See comment in test_alloc_parse_xdecl() */
8205     alloc_teardown();
8206     alloc_setup();
8207   }
8208   allocation_count = -1;
8209   if (i == 0)
8210     fail("External entity parsed despite duff allocator");
8211   if (i == alloc_test_max_repeats)
8212     fail("External entity not parsed at max allocation count");
8213 }
8214 END_TEST
8215 
8216 /* Test more allocation failure paths */
8217 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)8218 external_entity_alloc_set_encoding(XML_Parser parser, const XML_Char *context,
8219                                    const XML_Char *base,
8220                                    const XML_Char *systemId,
8221                                    const XML_Char *publicId) {
8222   /* As for external_entity_loader() */
8223   const char *text = "<?xml encoding='iso-8859-3'?>"
8224                      "\xC3\xA9";
8225   XML_Parser ext_parser;
8226   enum XML_Status status;
8227 
8228   UNUSED_P(base);
8229   UNUSED_P(systemId);
8230   UNUSED_P(publicId);
8231   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8232   if (ext_parser == NULL)
8233     return XML_STATUS_ERROR;
8234   if (! XML_SetEncoding(ext_parser, XCS("utf-8"))) {
8235     XML_ParserFree(ext_parser);
8236     return XML_STATUS_ERROR;
8237   }
8238   status
8239       = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
8240   XML_ParserFree(ext_parser);
8241   if (status == XML_STATUS_ERROR)
8242     return XML_STATUS_ERROR;
8243   return XML_STATUS_OK;
8244 }
8245 
START_TEST(test_alloc_ext_entity_set_encoding)8246 START_TEST(test_alloc_ext_entity_set_encoding) {
8247   const char *text = "<!DOCTYPE doc [\n"
8248                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
8249                      "]>\n"
8250                      "<doc>&en;</doc>";
8251   int i;
8252   const int max_allocation_count = 30;
8253 
8254   for (i = 0; i < max_allocation_count; i++) {
8255     XML_SetExternalEntityRefHandler(g_parser,
8256                                     external_entity_alloc_set_encoding);
8257     allocation_count = i;
8258     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8259         == XML_STATUS_OK)
8260       break;
8261     allocation_count = -1;
8262     /* See comment in test_alloc_parse_xdecl() */
8263     alloc_teardown();
8264     alloc_setup();
8265   }
8266   if (i == 0)
8267     fail("Encoding check succeeded despite failing allocator");
8268   if (i == max_allocation_count)
8269     fail("Encoding failed at max allocation count");
8270 }
8271 END_TEST
8272 
8273 static int XMLCALL
unknown_released_encoding_handler(void * data,const XML_Char * encoding,XML_Encoding * info)8274 unknown_released_encoding_handler(void *data, const XML_Char *encoding,
8275                                   XML_Encoding *info) {
8276   UNUSED_P(data);
8277   if (! xcstrcmp(encoding, XCS("unsupported-encoding"))) {
8278     int i;
8279 
8280     for (i = 0; i < 256; i++)
8281       info->map[i] = i;
8282     info->data = NULL;
8283     info->convert = NULL;
8284     info->release = dummy_release;
8285     return XML_STATUS_OK;
8286   }
8287   return XML_STATUS_ERROR;
8288 }
8289 
8290 /* Test the effects of allocation failure in internal entities.
8291  * Based on test_unknown_encoding_internal_entity
8292  */
START_TEST(test_alloc_internal_entity)8293 START_TEST(test_alloc_internal_entity) {
8294   const char *text = "<?xml version='1.0' encoding='unsupported-encoding'?>\n"
8295                      "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n"
8296                      "<test a='&foo;'/>";
8297   unsigned int i;
8298   const unsigned int max_alloc_count = 20;
8299 
8300   for (i = 0; i < max_alloc_count; i++) {
8301     allocation_count = i;
8302     XML_SetUnknownEncodingHandler(g_parser, unknown_released_encoding_handler,
8303                                   NULL);
8304     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8305         != XML_STATUS_ERROR)
8306       break;
8307     /* See comment in test_alloc_parse_xdecl() */
8308     alloc_teardown();
8309     alloc_setup();
8310   }
8311   if (i == 0)
8312     fail("Internal entity worked despite failing allocations");
8313   else if (i == max_alloc_count)
8314     fail("Internal entity failed at max allocation count");
8315 }
8316 END_TEST
8317 
8318 /* Test the robustness against allocation failure of element handling
8319  * Based on test_dtd_default_handling().
8320  */
START_TEST(test_alloc_dtd_default_handling)8321 START_TEST(test_alloc_dtd_default_handling) {
8322   const char *text = "<!DOCTYPE doc [\n"
8323                      "<!ENTITY e SYSTEM 'http://example.org/e'>\n"
8324                      "<!NOTATION n SYSTEM 'http://example.org/n'>\n"
8325                      "<!ENTITY e1 SYSTEM 'http://example.org/e' NDATA n>\n"
8326                      "<!ELEMENT doc (#PCDATA)>\n"
8327                      "<!ATTLIST doc a CDATA #IMPLIED>\n"
8328                      "<?pi in dtd?>\n"
8329                      "<!--comment in dtd-->\n"
8330                      "]>\n"
8331                      "<doc><![CDATA[text in doc]]></doc>";
8332   const XML_Char *expected = XCS("\n\n\n\n\n\n\n\n\n<doc>text in doc</doc>");
8333   CharData storage;
8334   int i;
8335   const int max_alloc_count = 25;
8336 
8337   for (i = 0; i < max_alloc_count; i++) {
8338     allocation_count = i;
8339     dummy_handler_flags = 0;
8340     XML_SetDefaultHandler(g_parser, accumulate_characters);
8341     XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_handler,
8342                               dummy_end_doctype_handler);
8343     XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
8344     XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
8345     XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
8346     XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
8347     XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
8348     XML_SetCommentHandler(g_parser, dummy_comment_handler);
8349     XML_SetCdataSectionHandler(g_parser, dummy_start_cdata_handler,
8350                                dummy_end_cdata_handler);
8351     XML_SetUnparsedEntityDeclHandler(g_parser,
8352                                      dummy_unparsed_entity_decl_handler);
8353     CharData_Init(&storage);
8354     XML_SetUserData(g_parser, &storage);
8355     XML_SetCharacterDataHandler(g_parser, accumulate_characters);
8356     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8357         != XML_STATUS_ERROR)
8358       break;
8359     /* See comment in test_alloc_parse_xdecl() */
8360     alloc_teardown();
8361     alloc_setup();
8362   }
8363   if (i == 0)
8364     fail("Default DTD parsed despite allocation failures");
8365   if (i == max_alloc_count)
8366     fail("Default DTD not parsed with maximum alloc count");
8367   CharData_CheckXMLChars(&storage, expected);
8368   if (dummy_handler_flags
8369       != (DUMMY_START_DOCTYPE_HANDLER_FLAG | DUMMY_END_DOCTYPE_HANDLER_FLAG
8370           | DUMMY_ENTITY_DECL_HANDLER_FLAG | DUMMY_NOTATION_DECL_HANDLER_FLAG
8371           | DUMMY_ELEMENT_DECL_HANDLER_FLAG | DUMMY_ATTLIST_DECL_HANDLER_FLAG
8372           | DUMMY_COMMENT_HANDLER_FLAG | DUMMY_PI_HANDLER_FLAG
8373           | DUMMY_START_CDATA_HANDLER_FLAG | DUMMY_END_CDATA_HANDLER_FLAG
8374           | DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG))
8375     fail("Not all handlers were called");
8376 }
8377 END_TEST
8378 
8379 /* Test robustness of XML_SetEncoding() with a failing allocator */
START_TEST(test_alloc_explicit_encoding)8380 START_TEST(test_alloc_explicit_encoding) {
8381   int i;
8382   const int max_alloc_count = 5;
8383 
8384   for (i = 0; i < max_alloc_count; i++) {
8385     allocation_count = i;
8386     if (XML_SetEncoding(g_parser, XCS("us-ascii")) == XML_STATUS_OK)
8387       break;
8388   }
8389   if (i == 0)
8390     fail("Encoding set despite failing allocator");
8391   else if (i == max_alloc_count)
8392     fail("Encoding not set at max allocation count");
8393 }
8394 END_TEST
8395 
8396 /* Test robustness of XML_SetBase against a failing allocator */
START_TEST(test_alloc_set_base)8397 START_TEST(test_alloc_set_base) {
8398   const XML_Char *new_base = XCS("/local/file/name.xml");
8399   int i;
8400   const int max_alloc_count = 5;
8401 
8402   for (i = 0; i < max_alloc_count; i++) {
8403     allocation_count = i;
8404     if (XML_SetBase(g_parser, new_base) == XML_STATUS_OK)
8405       break;
8406   }
8407   if (i == 0)
8408     fail("Base set despite failing allocator");
8409   else if (i == max_alloc_count)
8410     fail("Base not set with max allocation count");
8411 }
8412 END_TEST
8413 
8414 /* Test buffer extension in the face of a duff reallocator */
START_TEST(test_alloc_realloc_buffer)8415 START_TEST(test_alloc_realloc_buffer) {
8416   const char *text = get_buffer_test_text;
8417   void *buffer;
8418   int i;
8419   const int max_realloc_count = 10;
8420 
8421   /* Get a smallish buffer */
8422   for (i = 0; i < max_realloc_count; i++) {
8423     reallocation_count = i;
8424     buffer = XML_GetBuffer(g_parser, 1536);
8425     if (buffer == NULL)
8426       fail("1.5K buffer reallocation failed");
8427     assert(buffer != NULL);
8428     memcpy(buffer, text, strlen(text));
8429     if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE)
8430         == XML_STATUS_OK)
8431       break;
8432     /* See comment in test_alloc_parse_xdecl() */
8433     alloc_teardown();
8434     alloc_setup();
8435   }
8436   reallocation_count = -1;
8437   if (i == 0)
8438     fail("Parse succeeded with no reallocation");
8439   else if (i == max_realloc_count)
8440     fail("Parse failed with max reallocation count");
8441 }
8442 END_TEST
8443 
8444 /* Same test for external entity parsers */
8445 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)8446 external_entity_reallocator(XML_Parser parser, const XML_Char *context,
8447                             const XML_Char *base, const XML_Char *systemId,
8448                             const XML_Char *publicId) {
8449   const char *text = get_buffer_test_text;
8450   XML_Parser ext_parser;
8451   void *buffer;
8452   enum XML_Status status;
8453 
8454   UNUSED_P(base);
8455   UNUSED_P(systemId);
8456   UNUSED_P(publicId);
8457   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8458   if (ext_parser == NULL)
8459     fail("Could not create external entity parser");
8460 
8461   reallocation_count = (intptr_t)XML_GetUserData(parser);
8462   buffer = XML_GetBuffer(ext_parser, 1536);
8463   if (buffer == NULL)
8464     fail("Buffer allocation failed");
8465   assert(buffer != NULL);
8466   memcpy(buffer, text, strlen(text));
8467   status = XML_ParseBuffer(ext_parser, (int)strlen(text), XML_FALSE);
8468   reallocation_count = -1;
8469   XML_ParserFree(ext_parser);
8470   return (status == XML_STATUS_OK) ? XML_STATUS_OK : XML_STATUS_ERROR;
8471 }
8472 
START_TEST(test_alloc_ext_entity_realloc_buffer)8473 START_TEST(test_alloc_ext_entity_realloc_buffer) {
8474   const char *text = "<!DOCTYPE doc [\n"
8475                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
8476                      "]>\n"
8477                      "<doc>&en;</doc>";
8478   int i;
8479   const int max_realloc_count = 10;
8480 
8481   for (i = 0; i < max_realloc_count; i++) {
8482     XML_SetExternalEntityRefHandler(g_parser, external_entity_reallocator);
8483     XML_SetUserData(g_parser, (void *)(intptr_t)i);
8484     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8485         == XML_STATUS_OK)
8486       break;
8487     /* See comment in test_alloc_parse_xdecl() */
8488     alloc_teardown();
8489     alloc_setup();
8490   }
8491   if (i == 0)
8492     fail("Succeeded with no reallocations");
8493   if (i == max_realloc_count)
8494     fail("Failed with max reallocations");
8495 }
8496 END_TEST
8497 
8498 /* Test elements with many attributes are handled correctly */
START_TEST(test_alloc_realloc_many_attributes)8499 START_TEST(test_alloc_realloc_many_attributes) {
8500   const char *text = "<!DOCTYPE doc [\n"
8501                      "<!ATTLIST doc za CDATA 'default'>\n"
8502                      "<!ATTLIST doc zb CDATA 'def2'>\n"
8503                      "<!ATTLIST doc zc CDATA 'def3'>\n"
8504                      "]>\n"
8505                      "<doc a='1'"
8506                      "     b='2'"
8507                      "     c='3'"
8508                      "     d='4'"
8509                      "     e='5'"
8510                      "     f='6'"
8511                      "     g='7'"
8512                      "     h='8'"
8513                      "     i='9'"
8514                      "     j='10'"
8515                      "     k='11'"
8516                      "     l='12'"
8517                      "     m='13'"
8518                      "     n='14'"
8519                      "     p='15'"
8520                      "     q='16'"
8521                      "     r='17'"
8522                      "     s='18'>"
8523                      "</doc>";
8524   int i;
8525   const int max_realloc_count = 10;
8526 
8527   for (i = 0; i < max_realloc_count; i++) {
8528     reallocation_count = i;
8529     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8530         != XML_STATUS_ERROR)
8531       break;
8532     /* See comment in test_alloc_parse_xdecl() */
8533     alloc_teardown();
8534     alloc_setup();
8535   }
8536   if (i == 0)
8537     fail("Parse succeeded despite no reallocations");
8538   if (i == max_realloc_count)
8539     fail("Parse failed at max reallocations");
8540 }
8541 END_TEST
8542 
8543 /* Test handling of a public entity with failing allocator */
START_TEST(test_alloc_public_entity_value)8544 START_TEST(test_alloc_public_entity_value) {
8545   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
8546                      "<doc></doc>\n";
8547   char dtd_text[]
8548       = "<!ELEMENT doc EMPTY>\n"
8549         "<!ENTITY % e1 PUBLIC 'foo' 'bar.ent'>\n"
8550         "<!ENTITY % "
8551         /* Each line is 64 characters */
8552         "ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345"
8553         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8554         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8555         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8556         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8557         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8558         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8559         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8560         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8561         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8562         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8563         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8564         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8565         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8566         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8567         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8568         " '%e1;'>\n"
8569         "%e1;\n";
8570   int i;
8571   const int max_alloc_count = 50;
8572 
8573   for (i = 0; i < max_alloc_count; i++) {
8574     allocation_count = i;
8575     dummy_handler_flags = 0;
8576     XML_SetUserData(g_parser, dtd_text);
8577     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8578     XML_SetExternalEntityRefHandler(g_parser, external_entity_public);
8579     /* Provoke a particular code path */
8580     XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
8581     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8582         != XML_STATUS_ERROR)
8583       break;
8584     /* See comment in test_alloc_parse_xdecl() */
8585     alloc_teardown();
8586     alloc_setup();
8587   }
8588   if (i == 0)
8589     fail("Parsing worked despite failing allocation");
8590   if (i == max_alloc_count)
8591     fail("Parsing failed at max allocation count");
8592   if (dummy_handler_flags != DUMMY_ENTITY_DECL_HANDLER_FLAG)
8593     fail("Entity declaration handler not called");
8594 }
8595 END_TEST
8596 
START_TEST(test_alloc_realloc_subst_public_entity_value)8597 START_TEST(test_alloc_realloc_subst_public_entity_value) {
8598   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
8599                      "<doc></doc>\n";
8600   char dtd_text[]
8601       = "<!ELEMENT doc EMPTY>\n"
8602         "<!ENTITY % "
8603         /* Each line is 64 characters */
8604         "ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345"
8605         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8606         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8607         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8608         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8609         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8610         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8611         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8612         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8613         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8614         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8615         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8616         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8617         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8618         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8619         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8620         " PUBLIC 'foo' 'bar.ent'>\n"
8621         "%ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345"
8622         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8623         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8624         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8625         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8626         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8627         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8628         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8629         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8630         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8631         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8632         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8633         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8634         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8635         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8636         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP;";
8637   int i;
8638   const int max_realloc_count = 10;
8639 
8640   for (i = 0; i < max_realloc_count; i++) {
8641     reallocation_count = i;
8642     XML_SetUserData(g_parser, dtd_text);
8643     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8644     XML_SetExternalEntityRefHandler(g_parser, external_entity_public);
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 reallocation");
8654   if (i == max_realloc_count)
8655     fail("Parsing failed at max reallocation count");
8656 }
8657 END_TEST
8658 
START_TEST(test_alloc_parse_public_doctype)8659 START_TEST(test_alloc_parse_public_doctype) {
8660   const char *text
8661       = "<?xml version='1.0' encoding='utf-8'?>\n"
8662         "<!DOCTYPE doc PUBLIC '"
8663         /* 64 characters per line */
8664         "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/"
8665         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8666         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8667         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8668         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8669         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8670         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8671         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8672         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8673         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8674         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8675         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8676         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8677         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8678         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8679         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8680         "' 'test'>\n"
8681         "<doc></doc>";
8682   int i;
8683   const int max_alloc_count = 25;
8684 
8685   for (i = 0; i < max_alloc_count; i++) {
8686     allocation_count = i;
8687     dummy_handler_flags = 0;
8688     XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_decl_handler,
8689                               dummy_end_doctype_decl_handler);
8690     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8691         != XML_STATUS_ERROR)
8692       break;
8693     /* See comment in test_alloc_parse_xdecl() */
8694     alloc_teardown();
8695     alloc_setup();
8696   }
8697   if (i == 0)
8698     fail("Parse succeeded despite failing allocator");
8699   if (i == max_alloc_count)
8700     fail("Parse failed at maximum allocation count");
8701   if (dummy_handler_flags
8702       != (DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG
8703           | DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG))
8704     fail("Doctype handler functions not called");
8705 }
8706 END_TEST
8707 
START_TEST(test_alloc_parse_public_doctype_long_name)8708 START_TEST(test_alloc_parse_public_doctype_long_name) {
8709   const char *text
8710       = "<?xml version='1.0' encoding='utf-8'?>\n"
8711         "<!DOCTYPE doc PUBLIC 'http://example.com/foo' '"
8712         /* 64 characters per line */
8713         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8714         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8715         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8716         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8717         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8718         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8719         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8720         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8721         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8722         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8723         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8724         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8725         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8726         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8727         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8728         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8729         "'>\n"
8730         "<doc></doc>";
8731   int i;
8732   const int max_alloc_count = 25;
8733 
8734   for (i = 0; i < max_alloc_count; i++) {
8735     allocation_count = i;
8736     XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_decl_handler,
8737                               dummy_end_doctype_decl_handler);
8738     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8739         != XML_STATUS_ERROR)
8740       break;
8741     /* See comment in test_alloc_parse_xdecl() */
8742     alloc_teardown();
8743     alloc_setup();
8744   }
8745   if (i == 0)
8746     fail("Parse succeeded despite failing allocator");
8747   if (i == max_alloc_count)
8748     fail("Parse failed at maximum allocation count");
8749 }
8750 END_TEST
8751 
8752 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)8753 external_entity_alloc(XML_Parser parser, const XML_Char *context,
8754                       const XML_Char *base, const XML_Char *systemId,
8755                       const XML_Char *publicId) {
8756   const char *text = (const char *)XML_GetUserData(parser);
8757   XML_Parser ext_parser;
8758   int parse_res;
8759 
8760   UNUSED_P(base);
8761   UNUSED_P(systemId);
8762   UNUSED_P(publicId);
8763   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8764   if (ext_parser == NULL)
8765     return XML_STATUS_ERROR;
8766   parse_res
8767       = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
8768   XML_ParserFree(ext_parser);
8769   return parse_res;
8770 }
8771 
8772 /* Test foreign DTD handling */
START_TEST(test_alloc_set_foreign_dtd)8773 START_TEST(test_alloc_set_foreign_dtd) {
8774   const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n"
8775                       "<doc>&entity;</doc>";
8776   char text2[] = "<!ELEMENT doc (#PCDATA)*>";
8777   int i;
8778   const int max_alloc_count = 25;
8779 
8780   for (i = 0; i < max_alloc_count; i++) {
8781     allocation_count = i;
8782     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8783     XML_SetUserData(g_parser, &text2);
8784     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
8785     if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE)
8786       fail("Could not set foreign DTD");
8787     if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_TRUE)
8788         != XML_STATUS_ERROR)
8789       break;
8790     /* See comment in test_alloc_parse_xdecl() */
8791     alloc_teardown();
8792     alloc_setup();
8793   }
8794   if (i == 0)
8795     fail("Parse succeeded despite failing allocator");
8796   if (i == max_alloc_count)
8797     fail("Parse failed at maximum allocation count");
8798 }
8799 END_TEST
8800 
8801 /* Test based on ibm/valid/P32/ibm32v04.xml */
START_TEST(test_alloc_attribute_enum_value)8802 START_TEST(test_alloc_attribute_enum_value) {
8803   const char *text = "<?xml version='1.0' standalone='no'?>\n"
8804                      "<!DOCTYPE animal SYSTEM 'test.dtd'>\n"
8805                      "<animal>This is a \n    <a/>  \n\nyellow tiger</animal>";
8806   char dtd_text[] = "<!ELEMENT animal (#PCDATA|a)*>\n"
8807                     "<!ELEMENT a EMPTY>\n"
8808                     "<!ATTLIST animal xml:space (default|preserve) 'preserve'>";
8809   int i;
8810   const int max_alloc_count = 30;
8811 
8812   for (i = 0; i < max_alloc_count; i++) {
8813     allocation_count = i;
8814     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
8815     XML_SetUserData(g_parser, dtd_text);
8816     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8817     /* An attribute list handler provokes a different code path */
8818     XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
8819     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8820         != XML_STATUS_ERROR)
8821       break;
8822     /* See comment in test_alloc_parse_xdecl() */
8823     alloc_teardown();
8824     alloc_setup();
8825   }
8826   if (i == 0)
8827     fail("Parse succeeded despite failing allocator");
8828   if (i == max_alloc_count)
8829     fail("Parse failed at maximum allocation count");
8830 }
8831 END_TEST
8832 
8833 /* Test attribute enums sufficient to overflow the string pool */
START_TEST(test_alloc_realloc_attribute_enum_value)8834 START_TEST(test_alloc_realloc_attribute_enum_value) {
8835   const char *text = "<?xml version='1.0' standalone='no'?>\n"
8836                      "<!DOCTYPE animal SYSTEM 'test.dtd'>\n"
8837                      "<animal>This is a yellow tiger</animal>";
8838   /* We wish to define a collection of attribute enums that will
8839    * cause the string pool storing them to have to expand.  This
8840    * means more than 1024 bytes, including the parentheses and
8841    * separator bars.
8842    */
8843   char dtd_text[]
8844       = "<!ELEMENT animal (#PCDATA)*>\n"
8845         "<!ATTLIST animal thing "
8846         "(default"
8847         /* Each line is 64 characters */
8848         "|ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8849         "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8850         "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8851         "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8852         "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8853         "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8854         "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8855         "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8856         "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8857         "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8858         "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8859         "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8860         "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8861         "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8862         "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8863         "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO)"
8864         " 'default'>";
8865   int i;
8866   const int max_realloc_count = 10;
8867 
8868   for (i = 0; i < max_realloc_count; i++) {
8869     reallocation_count = i;
8870     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
8871     XML_SetUserData(g_parser, dtd_text);
8872     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8873     /* An attribute list handler provokes a different code path */
8874     XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
8875     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8876         != XML_STATUS_ERROR)
8877       break;
8878     /* See comment in test_alloc_parse_xdecl() */
8879     alloc_teardown();
8880     alloc_setup();
8881   }
8882   if (i == 0)
8883     fail("Parse succeeded despite failing reallocator");
8884   if (i == max_realloc_count)
8885     fail("Parse failed at maximum reallocation count");
8886 }
8887 END_TEST
8888 
8889 /* Test attribute enums in a #IMPLIED attribute forcing pool growth */
START_TEST(test_alloc_realloc_implied_attribute)8890 START_TEST(test_alloc_realloc_implied_attribute) {
8891   /* Forcing this particular code path is a balancing act.  The
8892    * addition of the closing parenthesis and terminal NUL must be
8893    * what pushes the string of enums over the 1024-byte limit,
8894    * otherwise a different code path will pick up the realloc.
8895    */
8896   const char *text
8897       = "<!DOCTYPE doc [\n"
8898         "<!ELEMENT doc EMPTY>\n"
8899         "<!ATTLIST doc a "
8900         /* Each line is 64 characters */
8901         "(ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8902         "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8903         "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8904         "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8905         "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8906         "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8907         "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8908         "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8909         "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8910         "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8911         "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8912         "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8913         "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8914         "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8915         "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8916         "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN)"
8917         " #IMPLIED>\n"
8918         "]><doc/>";
8919   int i;
8920   const int max_realloc_count = 10;
8921 
8922   for (i = 0; i < max_realloc_count; i++) {
8923     reallocation_count = i;
8924     XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
8925     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8926         != XML_STATUS_ERROR)
8927       break;
8928     /* See comment in test_alloc_parse_xdecl() */
8929     alloc_teardown();
8930     alloc_setup();
8931   }
8932   if (i == 0)
8933     fail("Parse succeeded despite failing reallocator");
8934   if (i == max_realloc_count)
8935     fail("Parse failed at maximum reallocation count");
8936 }
8937 END_TEST
8938 
8939 /* Test attribute enums in a defaulted attribute forcing pool growth */
START_TEST(test_alloc_realloc_default_attribute)8940 START_TEST(test_alloc_realloc_default_attribute) {
8941   /* Forcing this particular code path is a balancing act.  The
8942    * addition of the closing parenthesis and terminal NUL must be
8943    * what pushes the string of enums over the 1024-byte limit,
8944    * otherwise a different code path will pick up the realloc.
8945    */
8946   const char *text
8947       = "<!DOCTYPE doc [\n"
8948         "<!ELEMENT doc EMPTY>\n"
8949         "<!ATTLIST doc a "
8950         /* Each line is 64 characters */
8951         "(ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8952         "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8953         "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8954         "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8955         "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8956         "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8957         "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8958         "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8959         "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8960         "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8961         "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8962         "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8963         "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8964         "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8965         "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8966         "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN)"
8967         " 'ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO'"
8968         ">\n]><doc/>";
8969   int i;
8970   const int max_realloc_count = 10;
8971 
8972   for (i = 0; i < max_realloc_count; i++) {
8973     reallocation_count = i;
8974     XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
8975     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8976         != XML_STATUS_ERROR)
8977       break;
8978     /* See comment in test_alloc_parse_xdecl() */
8979     alloc_teardown();
8980     alloc_setup();
8981   }
8982   if (i == 0)
8983     fail("Parse succeeded despite failing reallocator");
8984   if (i == max_realloc_count)
8985     fail("Parse failed at maximum reallocation count");
8986 }
8987 END_TEST
8988 
8989 /* Test long notation name with dodgy allocator */
START_TEST(test_alloc_notation)8990 START_TEST(test_alloc_notation) {
8991   const char *text
8992       = "<!DOCTYPE doc [\n"
8993         "<!NOTATION "
8994         /* Each line is 64 characters */
8995         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8996         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8997         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8998         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8999         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9000         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9001         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9002         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9003         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9004         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9005         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9006         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9007         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9008         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9009         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9010         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9011         " SYSTEM 'http://example.org/n'>\n"
9012         "<!ENTITY e SYSTEM 'http://example.org/e' NDATA "
9013         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9014         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9015         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9016         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9017         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9018         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9019         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9020         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9021         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9022         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9023         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9024         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9025         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9026         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9027         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9028         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9029         ">\n"
9030         "<!ELEMENT doc EMPTY>\n"
9031         "]>\n<doc/>";
9032   int i;
9033   const int max_alloc_count = 20;
9034 
9035   for (i = 0; i < max_alloc_count; i++) {
9036     allocation_count = i;
9037     dummy_handler_flags = 0;
9038     XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
9039     XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
9040     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9041         != XML_STATUS_ERROR)
9042       break;
9043     /* See comment in test_alloc_parse_xdecl() */
9044     alloc_teardown();
9045     alloc_setup();
9046   }
9047   if (i == 0)
9048     fail("Parse succeeded despite allocation failures");
9049   if (i == max_alloc_count)
9050     fail("Parse failed at maximum allocation count");
9051   if (dummy_handler_flags
9052       != (DUMMY_ENTITY_DECL_HANDLER_FLAG | DUMMY_NOTATION_DECL_HANDLER_FLAG))
9053     fail("Entity declaration handler not called");
9054 }
9055 END_TEST
9056 
9057 /* Test public notation with dodgy allocator */
START_TEST(test_alloc_public_notation)9058 START_TEST(test_alloc_public_notation) {
9059   const char *text
9060       = "<!DOCTYPE doc [\n"
9061         "<!NOTATION note PUBLIC '"
9062         /* 64 characters per line */
9063         "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/"
9064         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9065         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9066         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9067         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9068         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9069         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9070         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9071         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9072         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9073         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9074         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9075         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9076         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9077         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9078         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9079         "' 'foo'>\n"
9080         "<!ENTITY e SYSTEM 'http://example.com/e' NDATA note>\n"
9081         "<!ELEMENT doc EMPTY>\n"
9082         "]>\n<doc/>";
9083   int i;
9084   const int max_alloc_count = 20;
9085 
9086   for (i = 0; i < max_alloc_count; i++) {
9087     allocation_count = i;
9088     dummy_handler_flags = 0;
9089     XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
9090     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9091         != XML_STATUS_ERROR)
9092       break;
9093     /* See comment in test_alloc_parse_xdecl() */
9094     alloc_teardown();
9095     alloc_setup();
9096   }
9097   if (i == 0)
9098     fail("Parse succeeded despite allocation failures");
9099   if (i == max_alloc_count)
9100     fail("Parse failed at maximum allocation count");
9101   if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG)
9102     fail("Notation handler not called");
9103 }
9104 END_TEST
9105 
9106 /* Test public notation with dodgy allocator */
START_TEST(test_alloc_system_notation)9107 START_TEST(test_alloc_system_notation) {
9108   const char *text
9109       = "<!DOCTYPE doc [\n"
9110         "<!NOTATION note SYSTEM '"
9111         /* 64 characters per line */
9112         "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/"
9113         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9114         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9115         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9116         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9117         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9118         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9119         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9120         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9121         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9122         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9123         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9124         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9125         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9126         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9127         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9128         "'>\n"
9129         "<!ENTITY e SYSTEM 'http://example.com/e' NDATA note>\n"
9130         "<!ELEMENT doc EMPTY>\n"
9131         "]>\n<doc/>";
9132   int i;
9133   const int max_alloc_count = 20;
9134 
9135   for (i = 0; i < max_alloc_count; i++) {
9136     allocation_count = i;
9137     dummy_handler_flags = 0;
9138     XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
9139     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9140         != XML_STATUS_ERROR)
9141       break;
9142     /* See comment in test_alloc_parse_xdecl() */
9143     alloc_teardown();
9144     alloc_setup();
9145   }
9146   if (i == 0)
9147     fail("Parse succeeded despite allocation failures");
9148   if (i == max_alloc_count)
9149     fail("Parse failed at maximum allocation count");
9150   if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG)
9151     fail("Notation handler not called");
9152 }
9153 END_TEST
9154 
START_TEST(test_alloc_nested_groups)9155 START_TEST(test_alloc_nested_groups) {
9156   const char *text
9157       = "<!DOCTYPE doc [\n"
9158         "<!ELEMENT doc "
9159         /* Sixteen elements per line */
9160         "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,"
9161         "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?"
9162         "))))))))))))))))))))))))))))))))>\n"
9163         "<!ELEMENT e EMPTY>"
9164         "]>\n"
9165         "<doc><e/></doc>";
9166   CharData storage;
9167   int i;
9168   const int max_alloc_count = 20;
9169 
9170   for (i = 0; i < max_alloc_count; i++) {
9171     allocation_count = i;
9172     CharData_Init(&storage);
9173     XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
9174     XML_SetStartElementHandler(g_parser, record_element_start_handler);
9175     XML_SetUserData(g_parser, &storage);
9176     dummy_handler_flags = 0;
9177     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9178         != XML_STATUS_ERROR)
9179       break;
9180     /* See comment in test_alloc_parse_xdecl() */
9181     alloc_teardown();
9182     alloc_setup();
9183   }
9184 
9185   if (i == 0)
9186     fail("Parse succeeded despite failing reallocator");
9187   if (i == max_alloc_count)
9188     fail("Parse failed at maximum reallocation count");
9189   CharData_CheckXMLChars(&storage, XCS("doce"));
9190   if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9191     fail("Element handler not fired");
9192 }
9193 END_TEST
9194 
START_TEST(test_alloc_realloc_nested_groups)9195 START_TEST(test_alloc_realloc_nested_groups) {
9196   const char *text
9197       = "<!DOCTYPE doc [\n"
9198         "<!ELEMENT doc "
9199         /* Sixteen elements per line */
9200         "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,"
9201         "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?"
9202         "))))))))))))))))))))))))))))))))>\n"
9203         "<!ELEMENT e EMPTY>"
9204         "]>\n"
9205         "<doc><e/></doc>";
9206   CharData storage;
9207   int i;
9208   const int max_realloc_count = 10;
9209 
9210   for (i = 0; i < max_realloc_count; i++) {
9211     reallocation_count = i;
9212     CharData_Init(&storage);
9213     XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
9214     XML_SetStartElementHandler(g_parser, record_element_start_handler);
9215     XML_SetUserData(g_parser, &storage);
9216     dummy_handler_flags = 0;
9217     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9218         != XML_STATUS_ERROR)
9219       break;
9220     /* See comment in test_alloc_parse_xdecl() */
9221     alloc_teardown();
9222     alloc_setup();
9223   }
9224 
9225   if (i == 0)
9226     fail("Parse succeeded despite failing reallocator");
9227   if (i == max_realloc_count)
9228     fail("Parse failed at maximum reallocation count");
9229   CharData_CheckXMLChars(&storage, XCS("doce"));
9230   if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9231     fail("Element handler not fired");
9232 }
9233 END_TEST
9234 
START_TEST(test_alloc_large_group)9235 START_TEST(test_alloc_large_group) {
9236   const char *text = "<!DOCTYPE doc [\n"
9237                      "<!ELEMENT doc ("
9238                      "a1|a2|a3|a4|a5|a6|a7|a8|"
9239                      "b1|b2|b3|b4|b5|b6|b7|b8|"
9240                      "c1|c2|c3|c4|c5|c6|c7|c8|"
9241                      "d1|d2|d3|d4|d5|d6|d7|d8|"
9242                      "e1"
9243                      ")+>\n"
9244                      "]>\n"
9245                      "<doc>\n"
9246                      "<a1/>\n"
9247                      "</doc>\n";
9248   int i;
9249   const int max_alloc_count = 50;
9250 
9251   for (i = 0; i < max_alloc_count; i++) {
9252     allocation_count = i;
9253     XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
9254     dummy_handler_flags = 0;
9255     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9256         != XML_STATUS_ERROR)
9257       break;
9258     /* See comment in test_alloc_parse_xdecl() */
9259     alloc_teardown();
9260     alloc_setup();
9261   }
9262   if (i == 0)
9263     fail("Parse succeeded despite failing allocator");
9264   if (i == max_alloc_count)
9265     fail("Parse failed at maximum allocation count");
9266   if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9267     fail("Element handler flag not raised");
9268 }
9269 END_TEST
9270 
START_TEST(test_alloc_realloc_group_choice)9271 START_TEST(test_alloc_realloc_group_choice) {
9272   const char *text = "<!DOCTYPE doc [\n"
9273                      "<!ELEMENT doc ("
9274                      "a1|a2|a3|a4|a5|a6|a7|a8|"
9275                      "b1|b2|b3|b4|b5|b6|b7|b8|"
9276                      "c1|c2|c3|c4|c5|c6|c7|c8|"
9277                      "d1|d2|d3|d4|d5|d6|d7|d8|"
9278                      "e1"
9279                      ")+>\n"
9280                      "]>\n"
9281                      "<doc>\n"
9282                      "<a1/>\n"
9283                      "<b2 attr='foo'>This is a foo</b2>\n"
9284                      "<c3></c3>\n"
9285                      "</doc>\n";
9286   int i;
9287   const int max_realloc_count = 10;
9288 
9289   for (i = 0; i < max_realloc_count; i++) {
9290     reallocation_count = i;
9291     XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
9292     dummy_handler_flags = 0;
9293     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9294         != XML_STATUS_ERROR)
9295       break;
9296     /* See comment in test_alloc_parse_xdecl() */
9297     alloc_teardown();
9298     alloc_setup();
9299   }
9300   if (i == 0)
9301     fail("Parse succeeded despite failing reallocator");
9302   if (i == max_realloc_count)
9303     fail("Parse failed at maximum reallocation count");
9304   if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9305     fail("Element handler flag not raised");
9306 }
9307 END_TEST
9308 
START_TEST(test_alloc_pi_in_epilog)9309 START_TEST(test_alloc_pi_in_epilog) {
9310   const char *text = "<doc></doc>\n"
9311                      "<?pi in epilog?>";
9312   int i;
9313   const int max_alloc_count = 15;
9314 
9315   for (i = 0; i < max_alloc_count; i++) {
9316     allocation_count = i;
9317     XML_SetProcessingInstructionHandler(g_parser, dummy_pi_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 completed despite failing allocator");
9328   if (i == max_alloc_count)
9329     fail("Parse failed at maximum allocation count");
9330   if (dummy_handler_flags != DUMMY_PI_HANDLER_FLAG)
9331     fail("Processing instruction handler not invoked");
9332 }
9333 END_TEST
9334 
START_TEST(test_alloc_comment_in_epilog)9335 START_TEST(test_alloc_comment_in_epilog) {
9336   const char *text = "<doc></doc>\n"
9337                      "<!-- comment in epilog -->";
9338   int i;
9339   const int max_alloc_count = 15;
9340 
9341   for (i = 0; i < max_alloc_count; i++) {
9342     allocation_count = i;
9343     XML_SetCommentHandler(g_parser, dummy_comment_handler);
9344     dummy_handler_flags = 0;
9345     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9346         != XML_STATUS_ERROR)
9347       break;
9348     /* See comment in test_alloc_parse_xdecl() */
9349     alloc_teardown();
9350     alloc_setup();
9351   }
9352   if (i == 0)
9353     fail("Parse completed despite failing allocator");
9354   if (i == max_alloc_count)
9355     fail("Parse failed at maximum allocation count");
9356   if (dummy_handler_flags != DUMMY_COMMENT_HANDLER_FLAG)
9357     fail("Processing instruction handler not invoked");
9358 }
9359 END_TEST
9360 
START_TEST(test_alloc_realloc_long_attribute_value)9361 START_TEST(test_alloc_realloc_long_attribute_value) {
9362   const char *text
9363       = "<!DOCTYPE doc [<!ENTITY foo '"
9364         /* Each line is 64 characters */
9365         "This entity will be substituted as an attribute value, and is   "
9366         "calculated to be exactly long enough that the terminating NUL   "
9367         "that the library adds internally will trigger the string pool to"
9368         "grow. GHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9369         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9370         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9371         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9372         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9373         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9374         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9375         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9376         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9377         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9378         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9379         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9380         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9381         "'>]>\n"
9382         "<doc a='&foo;'></doc>";
9383   int i;
9384   const int max_realloc_count = 10;
9385 
9386   for (i = 0; i < max_realloc_count; i++) {
9387     reallocation_count = i;
9388     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9389         != XML_STATUS_ERROR)
9390       break;
9391     /* See comment in test_alloc_parse_xdecl() */
9392     alloc_teardown();
9393     alloc_setup();
9394   }
9395   if (i == 0)
9396     fail("Parse succeeded despite failing reallocator");
9397   if (i == max_realloc_count)
9398     fail("Parse failed at maximum reallocation count");
9399 }
9400 END_TEST
9401 
START_TEST(test_alloc_attribute_whitespace)9402 START_TEST(test_alloc_attribute_whitespace) {
9403   const char *text = "<doc a=' '></doc>";
9404   int i;
9405   const int max_alloc_count = 15;
9406 
9407   for (i = 0; i < max_alloc_count; i++) {
9408     allocation_count = i;
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 succeeded despite failing allocator");
9418   if (i == max_alloc_count)
9419     fail("Parse failed at maximum allocation count");
9420 }
9421 END_TEST
9422 
START_TEST(test_alloc_attribute_predefined_entity)9423 START_TEST(test_alloc_attribute_predefined_entity) {
9424   const char *text = "<doc a='&amp;'></doc>";
9425   int i;
9426   const int max_alloc_count = 15;
9427 
9428   for (i = 0; i < max_alloc_count; i++) {
9429     allocation_count = i;
9430     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9431         != XML_STATUS_ERROR)
9432       break;
9433     /* See comment in test_alloc_parse_xdecl() */
9434     alloc_teardown();
9435     alloc_setup();
9436   }
9437   if (i == 0)
9438     fail("Parse succeeded despite failing allocator");
9439   if (i == max_alloc_count)
9440     fail("Parse failed at maximum allocation count");
9441 }
9442 END_TEST
9443 
9444 /* Test that a character reference at the end of a suitably long
9445  * default value for an attribute can trigger pool growth, and recovers
9446  * if the allocator fails on it.
9447  */
START_TEST(test_alloc_long_attr_default_with_char_ref)9448 START_TEST(test_alloc_long_attr_default_with_char_ref) {
9449   const char *text
9450       = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '"
9451         /* 64 characters per line */
9452         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9453         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9454         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9455         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9456         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9457         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9458         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9459         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9460         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9461         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9462         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9463         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9464         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9465         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9466         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9467         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHI"
9468         "&#x31;'>]>\n"
9469         "<doc/>";
9470   int i;
9471   const int max_alloc_count = 20;
9472 
9473   for (i = 0; i < max_alloc_count; i++) {
9474     allocation_count = i;
9475     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9476         != XML_STATUS_ERROR)
9477       break;
9478     /* See comment in test_alloc_parse_xdecl() */
9479     alloc_teardown();
9480     alloc_setup();
9481   }
9482   if (i == 0)
9483     fail("Parse succeeded despite failing allocator");
9484   if (i == max_alloc_count)
9485     fail("Parse failed at maximum allocation count");
9486 }
9487 END_TEST
9488 
9489 /* Test that a long character reference substitution triggers a pool
9490  * expansion correctly for an attribute value.
9491  */
START_TEST(test_alloc_long_attr_value)9492 START_TEST(test_alloc_long_attr_value) {
9493   const char *text
9494       = "<!DOCTYPE test [<!ENTITY foo '\n"
9495         /* 64 characters per line */
9496         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9497         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9498         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9499         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9500         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9501         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9502         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9503         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9504         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9505         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9506         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9507         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9508         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9509         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9510         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9511         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9512         "'>]>\n"
9513         "<test a='&foo;'/>";
9514   int i;
9515   const int max_alloc_count = 25;
9516 
9517   for (i = 0; i < max_alloc_count; i++) {
9518     allocation_count = i;
9519     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9520         != XML_STATUS_ERROR)
9521       break;
9522     /* See comment in test_alloc_parse_xdecl() */
9523     alloc_teardown();
9524     alloc_setup();
9525   }
9526   if (i == 0)
9527     fail("Parse succeeded despite failing allocator");
9528   if (i == max_alloc_count)
9529     fail("Parse failed at maximum allocation count");
9530 }
9531 END_TEST
9532 
9533 /* Test that an error in a nested parameter entity substitution is
9534  * handled correctly.  It seems unlikely that the code path being
9535  * exercised can be reached purely by carefully crafted XML, but an
9536  * allocation error in the right place will definitely do it.
9537  */
START_TEST(test_alloc_nested_entities)9538 START_TEST(test_alloc_nested_entities) {
9539   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n"
9540                      "<doc />";
9541   ExtFaults test_data
9542       = {"<!ENTITY % pe1 '"
9543          /* 64 characters per line */
9544          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9545          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9546          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9547          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9548          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9549          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9550          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9551          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9552          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9553          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9554          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9555          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9556          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9557          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9558          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9559          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9560          "'>\n"
9561          "<!ENTITY % pe2 '%pe1;'>\n"
9562          "%pe2;",
9563          "Memory Fail not faulted", NULL, XML_ERROR_NO_MEMORY};
9564 
9565   /* Causes an allocation error in a nested storeEntityValue() */
9566   allocation_count = 12;
9567   XML_SetUserData(g_parser, &test_data);
9568   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9569   XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
9570   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
9571                  "Entity allocation failure not noted");
9572 }
9573 END_TEST
9574 
START_TEST(test_alloc_realloc_param_entity_newline)9575 START_TEST(test_alloc_realloc_param_entity_newline) {
9576   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
9577                      "<doc/>";
9578   char dtd_text[]
9579       = "<!ENTITY % pe '<!ATTLIST doc att CDATA \""
9580         /* 64 characters per line */
9581         "This default value is carefully crafted so that the carriage    "
9582         "return right at the end of the entity string causes an internal "
9583         "string pool to have to grow.  This allows us to test the alloc  "
9584         "failure path from that point. OPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9585         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9586         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9587         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9588         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9589         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9590         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9591         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9592         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9593         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9594         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9595         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9596         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDE"
9597         "\">\n'>"
9598         "%pe;\n";
9599   int i;
9600   const int max_realloc_count = 5;
9601 
9602   for (i = 0; i < max_realloc_count; i++) {
9603     reallocation_count = i;
9604     XML_SetUserData(g_parser, dtd_text);
9605     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9606     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9607     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9608         != XML_STATUS_ERROR)
9609       break;
9610     /* See comment in test_alloc_parse_xdecl() */
9611     alloc_teardown();
9612     alloc_setup();
9613   }
9614   if (i == 0)
9615     fail("Parse succeeded despite failing reallocator");
9616   if (i == max_realloc_count)
9617     fail("Parse failed at maximum reallocation count");
9618 }
9619 END_TEST
9620 
START_TEST(test_alloc_realloc_ce_extends_pe)9621 START_TEST(test_alloc_realloc_ce_extends_pe) {
9622   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
9623                      "<doc/>";
9624   char dtd_text[]
9625       = "<!ENTITY % pe '<!ATTLIST doc att CDATA \""
9626         /* 64 characters per line */
9627         "This default value is carefully crafted so that the character   "
9628         "entity at the end causes an internal string pool to have to     "
9629         "grow.  This allows us to test the allocation failure path from  "
9630         "that point onwards. EFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9631         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9632         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9633         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9634         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9635         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9636         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9637         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9638         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9639         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9640         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9641         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9642         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFG&#x51;"
9643         "\">\n'>"
9644         "%pe;\n";
9645   int i;
9646   const int max_realloc_count = 5;
9647 
9648   for (i = 0; i < max_realloc_count; i++) {
9649     reallocation_count = i;
9650     XML_SetUserData(g_parser, dtd_text);
9651     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9652     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9653     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9654         != XML_STATUS_ERROR)
9655       break;
9656     /* See comment in test_alloc_parse_xdecl() */
9657     alloc_teardown();
9658     alloc_setup();
9659   }
9660   if (i == 0)
9661     fail("Parse succeeded despite failing reallocator");
9662   if (i == max_realloc_count)
9663     fail("Parse failed at maximum reallocation count");
9664 }
9665 END_TEST
9666 
START_TEST(test_alloc_realloc_attributes)9667 START_TEST(test_alloc_realloc_attributes) {
9668   const char *text = "<!DOCTYPE doc [\n"
9669                      "  <!ATTLIST doc\n"
9670                      "    a1  (a|b|c)   'a'\n"
9671                      "    a2  (foo|bar) #IMPLIED\n"
9672                      "    a3  NMTOKEN   #IMPLIED\n"
9673                      "    a4  NMTOKENS  #IMPLIED\n"
9674                      "    a5  ID        #IMPLIED\n"
9675                      "    a6  IDREF     #IMPLIED\n"
9676                      "    a7  IDREFS    #IMPLIED\n"
9677                      "    a8  ENTITY    #IMPLIED\n"
9678                      "    a9  ENTITIES  #IMPLIED\n"
9679                      "    a10 CDATA     #IMPLIED\n"
9680                      "  >]>\n"
9681                      "<doc>wombat</doc>\n";
9682   int i;
9683   const int max_realloc_count = 5;
9684 
9685   for (i = 0; i < max_realloc_count; i++) {
9686     reallocation_count = i;
9687     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9688         != XML_STATUS_ERROR)
9689       break;
9690     /* See comment in test_alloc_parse_xdecl() */
9691     alloc_teardown();
9692     alloc_setup();
9693   }
9694 
9695   if (i == 0)
9696     fail("Parse succeeded despite failing reallocator");
9697   if (i == max_realloc_count)
9698     fail("Parse failed at maximum reallocation count");
9699 }
9700 END_TEST
9701 
START_TEST(test_alloc_long_doc_name)9702 START_TEST(test_alloc_long_doc_name) {
9703   const char *text =
9704       /* 64 characters per line */
9705       "<LongRootElementNameThatWillCauseTheNextAllocationToExpandTheStr"
9706       "ingPoolForTheDTDQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9707       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9708       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9709       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9710       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9711       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9712       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9713       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9714       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9715       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9716       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9717       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9718       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9719       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9720       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9721       " a='1'/>";
9722   int i;
9723   const int max_alloc_count = 20;
9724 
9725   for (i = 0; i < max_alloc_count; i++) {
9726     allocation_count = i;
9727     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9728         != XML_STATUS_ERROR)
9729       break;
9730     /* See comment in test_alloc_parse_xdecl() */
9731     alloc_teardown();
9732     alloc_setup();
9733   }
9734   if (i == 0)
9735     fail("Parsing worked despite failing reallocations");
9736   else if (i == max_alloc_count)
9737     fail("Parsing failed even at max reallocation count");
9738 }
9739 END_TEST
9740 
START_TEST(test_alloc_long_base)9741 START_TEST(test_alloc_long_base) {
9742   const char *text = "<!DOCTYPE doc [\n"
9743                      "  <!ENTITY e SYSTEM 'foo'>\n"
9744                      "]>\n"
9745                      "<doc>&e;</doc>";
9746   char entity_text[] = "Hello world";
9747   const XML_Char *base =
9748       /* 64 characters per line */
9749       /* clang-format off */
9750         XCS("LongBaseURI/that/will/overflow/an/internal/buffer/and/cause/it/t")
9751         XCS("o/have/to/grow/PQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9752         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9753         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9754         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9755         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9756         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9757         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9758         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9759         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9760         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9761         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9762         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9763         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9764         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9765         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/");
9766   /* clang-format on */
9767   int i;
9768   const int max_alloc_count = 25;
9769 
9770   for (i = 0; i < max_alloc_count; i++) {
9771     allocation_count = i;
9772     XML_SetUserData(g_parser, entity_text);
9773     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9774     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9775     if (XML_SetBase(g_parser, base) == XML_STATUS_ERROR) {
9776       XML_ParserReset(g_parser, NULL);
9777       continue;
9778     }
9779     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9780         != XML_STATUS_ERROR)
9781       break;
9782     /* See comment in test_alloc_parse_xdecl() */
9783     alloc_teardown();
9784     alloc_setup();
9785   }
9786   if (i == 0)
9787     fail("Parsing worked despite failing allocations");
9788   else if (i == max_alloc_count)
9789     fail("Parsing failed even at max allocation count");
9790 }
9791 END_TEST
9792 
START_TEST(test_alloc_long_public_id)9793 START_TEST(test_alloc_long_public_id) {
9794   const char *text
9795       = "<!DOCTYPE doc [\n"
9796         "  <!ENTITY e PUBLIC '"
9797         /* 64 characters per line */
9798         "LongPublicIDThatShouldResultInAnInternalStringPoolGrowingAtASpec"
9799         "ificMomentKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9800         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9801         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9802         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9803         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9804         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9805         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9806         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9807         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9808         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9809         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9810         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9811         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9812         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9813         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9814         "' 'bar'>\n"
9815         "]>\n"
9816         "<doc>&e;</doc>";
9817   char entity_text[] = "Hello world";
9818   int i;
9819   const int max_alloc_count = 40;
9820 
9821   for (i = 0; i < max_alloc_count; i++) {
9822     allocation_count = i;
9823     XML_SetUserData(g_parser, entity_text);
9824     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9825     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9826     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9827         != XML_STATUS_ERROR)
9828       break;
9829     /* See comment in test_alloc_parse_xdecl() */
9830     alloc_teardown();
9831     alloc_setup();
9832   }
9833   if (i == 0)
9834     fail("Parsing worked despite failing allocations");
9835   else if (i == max_alloc_count)
9836     fail("Parsing failed even at max allocation count");
9837 }
9838 END_TEST
9839 
START_TEST(test_alloc_long_entity_value)9840 START_TEST(test_alloc_long_entity_value) {
9841   const char *text
9842       = "<!DOCTYPE doc [\n"
9843         "  <!ENTITY e1 '"
9844         /* 64 characters per line */
9845         "Long entity value that should provoke a string pool to grow whil"
9846         "e setting up to parse the external entity below. xyz0123456789AB"
9847         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9848         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9849         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9850         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9851         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9852         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9853         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9854         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9855         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9856         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9857         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9858         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9859         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9860         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9861         "'>\n"
9862         "  <!ENTITY e2 SYSTEM 'bar'>\n"
9863         "]>\n"
9864         "<doc>&e2;</doc>";
9865   char entity_text[] = "Hello world";
9866   int i;
9867   const int max_alloc_count = 40;
9868 
9869   for (i = 0; i < max_alloc_count; i++) {
9870     allocation_count = i;
9871     XML_SetUserData(g_parser, entity_text);
9872     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9873     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9874     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9875         != XML_STATUS_ERROR)
9876       break;
9877     /* See comment in test_alloc_parse_xdecl() */
9878     alloc_teardown();
9879     alloc_setup();
9880   }
9881   if (i == 0)
9882     fail("Parsing worked despite failing allocations");
9883   else if (i == max_alloc_count)
9884     fail("Parsing failed even at max allocation count");
9885 }
9886 END_TEST
9887 
START_TEST(test_alloc_long_notation)9888 START_TEST(test_alloc_long_notation) {
9889   const char *text
9890       = "<!DOCTYPE doc [\n"
9891         "  <!NOTATION note SYSTEM '"
9892         /* 64 characters per line */
9893         "ALongNotationNameThatShouldProvokeStringPoolGrowthWhileCallingAn"
9894         "ExternalEntityParserUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9895         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9896         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9897         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9898         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9899         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9900         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9901         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9902         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9903         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9904         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9905         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9906         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9907         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9908         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9909         "'>\n"
9910         "  <!ENTITY e1 SYSTEM 'foo' NDATA "
9911         /* 64 characters per line */
9912         "ALongNotationNameThatShouldProvokeStringPoolGrowthWhileCallingAn"
9913         "ExternalEntityParserUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9914         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9915         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9916         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9917         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9918         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9919         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9920         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9921         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9922         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9923         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9924         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9925         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9926         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9927         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9928         ">\n"
9929         "  <!ENTITY e2 SYSTEM 'bar'>\n"
9930         "]>\n"
9931         "<doc>&e2;</doc>";
9932   ExtOption options[]
9933       = {{XCS("foo"), "Entity Foo"}, {XCS("bar"), "Entity Bar"}, {NULL, NULL}};
9934   int i;
9935   const int max_alloc_count = 40;
9936 
9937   for (i = 0; i < max_alloc_count; i++) {
9938     allocation_count = i;
9939     XML_SetUserData(g_parser, options);
9940     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9941     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
9942     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9943         != XML_STATUS_ERROR)
9944       break;
9945 
9946     /* See comment in test_alloc_parse_xdecl() */
9947     alloc_teardown();
9948     alloc_setup();
9949   }
9950   if (i == 0)
9951     fail("Parsing worked despite failing allocations");
9952   else if (i == max_alloc_count)
9953     fail("Parsing failed even at max allocation count");
9954 }
9955 END_TEST
9956 
9957 static void
nsalloc_setup(void)9958 nsalloc_setup(void) {
9959   XML_Memory_Handling_Suite memsuite = {duff_allocator, duff_reallocator, free};
9960   XML_Char ns_sep[2] = {' ', '\0'};
9961 
9962   /* Ensure the parser creation will go through */
9963   allocation_count = ALLOC_ALWAYS_SUCCEED;
9964   reallocation_count = REALLOC_ALWAYS_SUCCEED;
9965   g_parser = XML_ParserCreate_MM(NULL, &memsuite, ns_sep);
9966   if (g_parser == NULL)
9967     fail("Parser not created");
9968 }
9969 
9970 static void
nsalloc_teardown(void)9971 nsalloc_teardown(void) {
9972   basic_teardown();
9973 }
9974 
9975 /* Test the effects of allocation failure in simple namespace parsing.
9976  * Based on test_ns_default_with_empty_uri()
9977  */
START_TEST(test_nsalloc_xmlns)9978 START_TEST(test_nsalloc_xmlns) {
9979   const char *text = "<doc xmlns='http://example.org/'>\n"
9980                      "  <e xmlns=''/>\n"
9981                      "</doc>";
9982   unsigned int i;
9983   const unsigned int max_alloc_count = 30;
9984 
9985   for (i = 0; i < max_alloc_count; i++) {
9986     allocation_count = i;
9987     /* Exercise more code paths with a default handler */
9988     XML_SetDefaultHandler(g_parser, dummy_default_handler);
9989     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9990         != XML_STATUS_ERROR)
9991       break;
9992     /* Resetting the parser is insufficient, because some memory
9993      * allocations are cached within the parser.  Instead we use
9994      * the teardown and setup routines to ensure that we have the
9995      * right sort of parser back in our hands.
9996      */
9997     nsalloc_teardown();
9998     nsalloc_setup();
9999   }
10000   if (i == 0)
10001     fail("Parsing worked despite failing allocations");
10002   else if (i == max_alloc_count)
10003     fail("Parsing failed even at maximum allocation count");
10004 }
10005 END_TEST
10006 
10007 /* Test XML_ParseBuffer interface with namespace and a dicky allocator */
START_TEST(test_nsalloc_parse_buffer)10008 START_TEST(test_nsalloc_parse_buffer) {
10009   const char *text = "<doc>Hello</doc>";
10010   void *buffer;
10011 
10012   /* Try a parse before the start of the world */
10013   /* (Exercises new code path) */
10014   if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_ERROR)
10015     fail("Pre-init XML_ParseBuffer not faulted");
10016   if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_BUFFER)
10017     fail("Pre-init XML_ParseBuffer faulted for wrong reason");
10018 
10019   buffer = XML_GetBuffer(g_parser, 1 /* any small number greater than 0 */);
10020   if (buffer == NULL)
10021     fail("Could not acquire parse buffer");
10022 
10023   allocation_count = 0;
10024   if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_ERROR)
10025     fail("Pre-init XML_ParseBuffer not faulted");
10026   if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_MEMORY)
10027     fail("Pre-init XML_ParseBuffer faulted for wrong reason");
10028 
10029   /* Now with actual memory allocation */
10030   allocation_count = ALLOC_ALWAYS_SUCCEED;
10031   if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_OK)
10032     xml_failure(g_parser);
10033 
10034   /* Check that resuming an unsuspended parser is faulted */
10035   if (XML_ResumeParser(g_parser) != XML_STATUS_ERROR)
10036     fail("Resuming unsuspended parser not faulted");
10037   if (XML_GetErrorCode(g_parser) != XML_ERROR_NOT_SUSPENDED)
10038     xml_failure(g_parser);
10039 
10040   /* Get the parser into suspended state */
10041   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
10042   resumable = XML_TRUE;
10043   buffer = XML_GetBuffer(g_parser, (int)strlen(text));
10044   if (buffer == NULL)
10045     fail("Could not acquire parse buffer");
10046   assert(buffer != NULL);
10047   memcpy(buffer, text, strlen(text));
10048   if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE)
10049       != XML_STATUS_SUSPENDED)
10050     xml_failure(g_parser);
10051   if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE)
10052     xml_failure(g_parser);
10053   if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE)
10054       != XML_STATUS_ERROR)
10055     fail("Suspended XML_ParseBuffer not faulted");
10056   if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED)
10057     xml_failure(g_parser);
10058   if (XML_GetBuffer(g_parser, (int)strlen(text)) != NULL)
10059     fail("Suspended XML_GetBuffer not faulted");
10060 
10061   /* Get it going again and complete the world */
10062   XML_SetCharacterDataHandler(g_parser, NULL);
10063   if (XML_ResumeParser(g_parser) != XML_STATUS_OK)
10064     xml_failure(g_parser);
10065   if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE)
10066       != XML_STATUS_ERROR)
10067     fail("Post-finishing XML_ParseBuffer not faulted");
10068   if (XML_GetErrorCode(g_parser) != XML_ERROR_FINISHED)
10069     xml_failure(g_parser);
10070   if (XML_GetBuffer(g_parser, (int)strlen(text)) != NULL)
10071     fail("Post-finishing XML_GetBuffer not faulted");
10072 }
10073 END_TEST
10074 
10075 /* Check handling of long prefix names (pool growth) */
START_TEST(test_nsalloc_long_prefix)10076 START_TEST(test_nsalloc_long_prefix) {
10077   const char *text
10078       = "<"
10079         /* 64 characters per line */
10080         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10081         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10082         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10083         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10084         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10085         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10086         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10087         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10088         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10089         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10090         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10091         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10092         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10093         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10094         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10095         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10096         ":foo xmlns:"
10097         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10098         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10099         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10100         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10101         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10102         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10103         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10104         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10105         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10106         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10107         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10108         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10109         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10110         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10111         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10112         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10113         "='http://example.org/'>"
10114         "</"
10115         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10116         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10117         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10118         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10119         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10120         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10121         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10122         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10123         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10124         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10125         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10126         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10127         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10128         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10129         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10130         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10131         ":foo>";
10132   int i;
10133   const int max_alloc_count = 40;
10134 
10135   for (i = 0; i < max_alloc_count; i++) {
10136     allocation_count = i;
10137     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10138         != XML_STATUS_ERROR)
10139       break;
10140     /* See comment in test_nsalloc_xmlns() */
10141     nsalloc_teardown();
10142     nsalloc_setup();
10143   }
10144   if (i == 0)
10145     fail("Parsing worked despite failing allocations");
10146   else if (i == max_alloc_count)
10147     fail("Parsing failed even at max allocation count");
10148 }
10149 END_TEST
10150 
10151 /* Check handling of long uri names (pool growth) */
START_TEST(test_nsalloc_long_uri)10152 START_TEST(test_nsalloc_long_uri) {
10153   const char *text
10154       = "<foo:e xmlns:foo='http://example.org/"
10155         /* 64 characters per line */
10156         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10157         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10158         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10159         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10160         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10161         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10162         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10163         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10164         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10165         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10166         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10167         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10168         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10169         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10170         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10171         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10172         "' bar:a='12'\n"
10173         "xmlns:bar='http://example.org/"
10174         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10175         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10176         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10177         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10178         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10179         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10180         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10181         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10182         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10183         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10184         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10185         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10186         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10187         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10188         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10189         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10190         "'>"
10191         "</foo:e>";
10192   int i;
10193   const int max_alloc_count = 40;
10194 
10195   for (i = 0; i < max_alloc_count; i++) {
10196     allocation_count = i;
10197     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10198         != XML_STATUS_ERROR)
10199       break;
10200     /* See comment in test_nsalloc_xmlns() */
10201     nsalloc_teardown();
10202     nsalloc_setup();
10203   }
10204   if (i == 0)
10205     fail("Parsing worked despite failing allocations");
10206   else if (i == max_alloc_count)
10207     fail("Parsing failed even at max allocation count");
10208 }
10209 END_TEST
10210 
10211 /* Test handling of long attribute names with prefixes */
START_TEST(test_nsalloc_long_attr)10212 START_TEST(test_nsalloc_long_attr) {
10213   const char *text
10214       = "<foo:e xmlns:foo='http://example.org/' bar:"
10215         /* 64 characters per line */
10216         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10217         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10218         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10219         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10220         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10221         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10222         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10223         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10224         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10225         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10226         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10227         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10228         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10229         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10230         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10231         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10232         "='12'\n"
10233         "xmlns:bar='http://example.org/'>"
10234         "</foo:e>";
10235   int i;
10236   const int max_alloc_count = 40;
10237 
10238   for (i = 0; i < max_alloc_count; i++) {
10239     allocation_count = i;
10240     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10241         != XML_STATUS_ERROR)
10242       break;
10243     /* See comment in test_nsalloc_xmlns() */
10244     nsalloc_teardown();
10245     nsalloc_setup();
10246   }
10247   if (i == 0)
10248     fail("Parsing worked despite failing allocations");
10249   else if (i == max_alloc_count)
10250     fail("Parsing failed even at max allocation count");
10251 }
10252 END_TEST
10253 
10254 /* Test handling of an attribute name with a long namespace prefix */
START_TEST(test_nsalloc_long_attr_prefix)10255 START_TEST(test_nsalloc_long_attr_prefix) {
10256   const char *text
10257       = "<foo:e xmlns:foo='http://example.org/' "
10258         /* 64 characters per line */
10259         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10260         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10261         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10262         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10263         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10264         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10265         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10266         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10267         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10268         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10269         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10270         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10271         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10272         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10273         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10274         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10275         ":a='12'\n"
10276         "xmlns:"
10277         /* 64 characters per line */
10278         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10279         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10280         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10281         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10282         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10283         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10284         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10285         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10286         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10287         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10288         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10289         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10290         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10291         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10292         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10293         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10294         "='http://example.org/'>"
10295         "</foo:e>";
10296   const XML_Char *elemstr[] = {
10297       /* clang-format off */
10298         XCS("http://example.org/ e foo"),
10299         XCS("http://example.org/ a ")
10300         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10301         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10302         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10303         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10304         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10305         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10306         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10307         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10308         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10309         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10310         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10311         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10312         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10313         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10314         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10315         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10316       /* clang-format on */
10317   };
10318   int i;
10319   const int max_alloc_count = 40;
10320 
10321   for (i = 0; i < max_alloc_count; i++) {
10322     allocation_count = i;
10323     XML_SetReturnNSTriplet(g_parser, XML_TRUE);
10324     XML_SetUserData(g_parser, (void *)elemstr);
10325     XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
10326     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10327         != XML_STATUS_ERROR)
10328       break;
10329     /* See comment in test_nsalloc_xmlns() */
10330     nsalloc_teardown();
10331     nsalloc_setup();
10332   }
10333   if (i == 0)
10334     fail("Parsing worked despite failing allocations");
10335   else if (i == max_alloc_count)
10336     fail("Parsing failed even at max allocation count");
10337 }
10338 END_TEST
10339 
10340 /* Test attribute handling in the face of a dodgy reallocator */
START_TEST(test_nsalloc_realloc_attributes)10341 START_TEST(test_nsalloc_realloc_attributes) {
10342   const char *text = "<foo:e xmlns:foo='http://example.org/' bar:a='12'\n"
10343                      "       xmlns:bar='http://example.org/'>"
10344                      "</foo:e>";
10345   int i;
10346   const int max_realloc_count = 10;
10347 
10348   for (i = 0; i < max_realloc_count; i++) {
10349     reallocation_count = i;
10350     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10351         != XML_STATUS_ERROR)
10352       break;
10353     /* See comment in test_nsalloc_xmlns() */
10354     nsalloc_teardown();
10355     nsalloc_setup();
10356   }
10357   if (i == 0)
10358     fail("Parsing worked despite failing reallocations");
10359   else if (i == max_realloc_count)
10360     fail("Parsing failed at max reallocation count");
10361 }
10362 END_TEST
10363 
10364 /* Test long element names with namespaces under a failing allocator */
START_TEST(test_nsalloc_long_element)10365 START_TEST(test_nsalloc_long_element) {
10366   const char *text
10367       = "<foo:thisisalongenoughelementnametotriggerareallocation\n"
10368         " xmlns:foo='http://example.org/' bar:a='12'\n"
10369         " xmlns:bar='http://example.org/'>"
10370         "</foo:thisisalongenoughelementnametotriggerareallocation>";
10371   const XML_Char *elemstr[]
10372       = {XCS("http://example.org/")
10373              XCS(" thisisalongenoughelementnametotriggerareallocation foo"),
10374          XCS("http://example.org/ a bar")};
10375   int i;
10376   const int max_alloc_count = 30;
10377 
10378   for (i = 0; i < max_alloc_count; i++) {
10379     allocation_count = i;
10380     XML_SetReturnNSTriplet(g_parser, XML_TRUE);
10381     XML_SetUserData(g_parser, (void *)elemstr);
10382     XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
10383     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10384         != XML_STATUS_ERROR)
10385       break;
10386     /* See comment in test_nsalloc_xmlns() */
10387     nsalloc_teardown();
10388     nsalloc_setup();
10389   }
10390   if (i == 0)
10391     fail("Parsing worked despite failing reallocations");
10392   else if (i == max_alloc_count)
10393     fail("Parsing failed at max reallocation count");
10394 }
10395 END_TEST
10396 
10397 /* Test the effects of reallocation failure when reassigning a
10398  * binding.
10399  *
10400  * XML_ParserReset does not free the BINDING structures used by a
10401  * parser, but instead adds them to an internal free list to be reused
10402  * as necessary.  Likewise the URI buffers allocated for the binding
10403  * aren't freed, but kept attached to their existing binding.  If the
10404  * new binding has a longer URI, it will need reallocation.  This test
10405  * provokes that reallocation, and tests the control path if it fails.
10406  */
START_TEST(test_nsalloc_realloc_binding_uri)10407 START_TEST(test_nsalloc_realloc_binding_uri) {
10408   const char *first = "<doc xmlns='http://example.org/'>\n"
10409                       "  <e xmlns='' />\n"
10410                       "</doc>";
10411   const char *second
10412       = "<doc xmlns='http://example.org/long/enough/URI/to/reallocate/'>\n"
10413         "  <e xmlns='' />\n"
10414         "</doc>";
10415   unsigned i;
10416   const unsigned max_realloc_count = 10;
10417 
10418   /* First, do a full parse that will leave bindings around */
10419   if (_XML_Parse_SINGLE_BYTES(g_parser, first, (int)strlen(first), XML_TRUE)
10420       == XML_STATUS_ERROR)
10421     xml_failure(g_parser);
10422 
10423   /* Now repeat with a longer URI and a duff reallocator */
10424   for (i = 0; i < max_realloc_count; i++) {
10425     XML_ParserReset(g_parser, NULL);
10426     reallocation_count = i;
10427     if (_XML_Parse_SINGLE_BYTES(g_parser, second, (int)strlen(second), XML_TRUE)
10428         != XML_STATUS_ERROR)
10429       break;
10430   }
10431   if (i == 0)
10432     fail("Parsing worked despite failing reallocation");
10433   else if (i == max_realloc_count)
10434     fail("Parsing failed at max reallocation count");
10435 }
10436 END_TEST
10437 
10438 /* Check handling of long prefix names (pool growth) */
START_TEST(test_nsalloc_realloc_long_prefix)10439 START_TEST(test_nsalloc_realloc_long_prefix) {
10440   const char *text
10441       = "<"
10442         /* 64 characters per line */
10443         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10444         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10445         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10446         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10447         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10448         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10449         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10450         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10451         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10452         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10453         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10454         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10455         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10456         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10457         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10458         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10459         ":foo xmlns:"
10460         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10461         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10462         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10463         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10464         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10465         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10466         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10467         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10468         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10469         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10470         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10471         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10472         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10473         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10474         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10475         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10476         "='http://example.org/'>"
10477         "</"
10478         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10479         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10480         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10481         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10482         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10483         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10484         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10485         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10486         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10487         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10488         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10489         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10490         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10491         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10492         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10493         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10494         ":foo>";
10495   int i;
10496   const int max_realloc_count = 12;
10497 
10498   for (i = 0; i < max_realloc_count; i++) {
10499     reallocation_count = i;
10500     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10501         != XML_STATUS_ERROR)
10502       break;
10503     /* See comment in test_nsalloc_xmlns() */
10504     nsalloc_teardown();
10505     nsalloc_setup();
10506   }
10507   if (i == 0)
10508     fail("Parsing worked despite failing reallocations");
10509   else if (i == max_realloc_count)
10510     fail("Parsing failed even at max reallocation count");
10511 }
10512 END_TEST
10513 
10514 /* Check handling of even long prefix names (different code path) */
START_TEST(test_nsalloc_realloc_longer_prefix)10515 START_TEST(test_nsalloc_realloc_longer_prefix) {
10516   const char *text
10517       = "<"
10518         /* 64 characters per line */
10519         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10520         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10521         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10522         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10523         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10524         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10525         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10526         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10527         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10528         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10529         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10530         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10531         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10532         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10533         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10534         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10535         "Q:foo xmlns:"
10536         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10537         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10538         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10539         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10540         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10541         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10542         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10543         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10544         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10545         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10546         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10547         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10548         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10549         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10550         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10551         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10552         "Q='http://example.org/'>"
10553         "</"
10554         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10555         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10556         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10557         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10558         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10559         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10560         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10561         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10562         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10563         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10564         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10565         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10566         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10567         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10568         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10569         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10570         "Q:foo>";
10571   int i;
10572   const int max_realloc_count = 12;
10573 
10574   for (i = 0; i < max_realloc_count; i++) {
10575     reallocation_count = i;
10576     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10577         != XML_STATUS_ERROR)
10578       break;
10579     /* See comment in test_nsalloc_xmlns() */
10580     nsalloc_teardown();
10581     nsalloc_setup();
10582   }
10583   if (i == 0)
10584     fail("Parsing worked despite failing reallocations");
10585   else if (i == max_realloc_count)
10586     fail("Parsing failed even at max reallocation count");
10587 }
10588 END_TEST
10589 
START_TEST(test_nsalloc_long_namespace)10590 START_TEST(test_nsalloc_long_namespace) {
10591   const char *text1
10592       = "<"
10593         /* 64 characters per line */
10594         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10595         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10596         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10597         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10598         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10599         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10600         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10601         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10602         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10603         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10604         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10605         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10606         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10607         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10608         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10609         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10610         ":e xmlns:"
10611         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10612         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10613         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10614         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10615         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10616         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10617         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10618         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10619         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10620         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10621         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10622         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10623         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10624         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10625         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10626         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10627         "='http://example.org/'>\n";
10628   const char *text2
10629       = "<"
10630         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10631         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10632         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10633         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10634         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10635         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10636         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10637         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10638         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10639         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10640         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10641         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10642         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10643         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10644         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10645         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10646         ":f "
10647         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10648         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10649         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10650         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10651         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10652         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10653         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10654         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10655         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10656         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10657         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10658         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10659         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10660         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10661         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10662         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10663         ":attr='foo'/>\n"
10664         "</"
10665         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10666         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10667         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10668         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10669         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10670         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10671         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10672         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10673         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10674         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10675         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10676         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10677         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10678         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10679         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10680         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10681         ":e>";
10682   int i;
10683   const int max_alloc_count = 40;
10684 
10685   for (i = 0; i < max_alloc_count; i++) {
10686     allocation_count = i;
10687     if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
10688             != XML_STATUS_ERROR
10689         && _XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2),
10690                                    XML_TRUE)
10691                != XML_STATUS_ERROR)
10692       break;
10693     /* See comment in test_nsalloc_xmlns() */
10694     nsalloc_teardown();
10695     nsalloc_setup();
10696   }
10697   if (i == 0)
10698     fail("Parsing worked despite failing allocations");
10699   else if (i == max_alloc_count)
10700     fail("Parsing failed even at max allocation count");
10701 }
10702 END_TEST
10703 
10704 /* Using a slightly shorter namespace name provokes allocations in
10705  * slightly different places in the code.
10706  */
START_TEST(test_nsalloc_less_long_namespace)10707 START_TEST(test_nsalloc_less_long_namespace) {
10708   const char *text
10709       = "<"
10710         /* 64 characters per line */
10711         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10712         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10713         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10714         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10715         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10716         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10717         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10718         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10719         ":e xmlns:"
10720         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10721         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10722         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10723         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10724         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10725         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10726         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10727         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10728         "='http://example.org/'>\n"
10729         "<"
10730         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10731         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10732         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10733         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10734         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10735         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10736         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10737         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10738         ":f "
10739         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10740         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10741         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10742         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10743         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10744         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10745         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10746         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10747         ":att='foo'/>\n"
10748         "</"
10749         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10750         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10751         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10752         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10753         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10754         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10755         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10756         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10757         ":e>";
10758   int i;
10759   const int max_alloc_count = 40;
10760 
10761   for (i = 0; i < max_alloc_count; i++) {
10762     allocation_count = i;
10763     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10764         != XML_STATUS_ERROR)
10765       break;
10766     /* See comment in test_nsalloc_xmlns() */
10767     nsalloc_teardown();
10768     nsalloc_setup();
10769   }
10770   if (i == 0)
10771     fail("Parsing worked despite failing allocations");
10772   else if (i == max_alloc_count)
10773     fail("Parsing failed even at max allocation count");
10774 }
10775 END_TEST
10776 
START_TEST(test_nsalloc_long_context)10777 START_TEST(test_nsalloc_long_context) {
10778   const char *text
10779       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10780         "  <!ATTLIST doc baz ID #REQUIRED>\n"
10781         "  <!ENTITY en SYSTEM 'bar'>\n"
10782         "]>\n"
10783         "<doc xmlns='http://example.org/"
10784         /* 64 characters per line */
10785         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10786         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10787         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10788         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10789         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10790         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10791         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10792         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10793         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10794         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10795         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10796         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10797         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10798         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10799         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10800         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKL"
10801         "' baz='2'>\n"
10802         "&en;"
10803         "</doc>";
10804   ExtOption options[] = {
10805       {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}};
10806   int i;
10807   const int max_alloc_count = 70;
10808 
10809   for (i = 0; i < max_alloc_count; i++) {
10810     allocation_count = i;
10811     XML_SetUserData(g_parser, options);
10812     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
10813     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
10814     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10815         != XML_STATUS_ERROR)
10816       break;
10817 
10818     /* See comment in test_nsalloc_xmlns() */
10819     nsalloc_teardown();
10820     nsalloc_setup();
10821   }
10822   if (i == 0)
10823     fail("Parsing worked despite failing allocations");
10824   else if (i == max_alloc_count)
10825     fail("Parsing failed even at max allocation count");
10826 }
10827 END_TEST
10828 
10829 /* This function is void; it will throw a fail() on error, so if it
10830  * returns normally it must have succeeded.
10831  */
10832 static void
context_realloc_test(const char * text)10833 context_realloc_test(const char *text) {
10834   ExtOption options[] = {
10835       {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}};
10836   int i;
10837   const int max_realloc_count = 6;
10838 
10839   for (i = 0; i < max_realloc_count; i++) {
10840     reallocation_count = i;
10841     XML_SetUserData(g_parser, options);
10842     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
10843     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
10844     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10845         != XML_STATUS_ERROR)
10846       break;
10847     /* See comment in test_nsalloc_xmlns() */
10848     nsalloc_teardown();
10849     nsalloc_setup();
10850   }
10851   if (i == 0)
10852     fail("Parsing worked despite failing reallocations");
10853   else if (i == max_realloc_count)
10854     fail("Parsing failed even at max reallocation count");
10855 }
10856 
START_TEST(test_nsalloc_realloc_long_context)10857 START_TEST(test_nsalloc_realloc_long_context) {
10858   const char *text
10859       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10860         "  <!ENTITY en SYSTEM 'bar'>\n"
10861         "]>\n"
10862         "<doc xmlns='http://example.org/"
10863         /* 64 characters per line */
10864         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10865         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10866         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10867         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10868         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10869         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10870         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10871         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10872         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10873         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10874         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10875         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10876         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10877         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10878         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10879         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKL"
10880         "'>\n"
10881         "&en;"
10882         "</doc>";
10883 
10884   context_realloc_test(text);
10885 }
10886 END_TEST
10887 
START_TEST(test_nsalloc_realloc_long_context_2)10888 START_TEST(test_nsalloc_realloc_long_context_2) {
10889   const char *text
10890       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10891         "  <!ENTITY en SYSTEM 'bar'>\n"
10892         "]>\n"
10893         "<doc xmlns='http://example.org/"
10894         /* 64 characters per line */
10895         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10896         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10897         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10898         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10899         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10900         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10901         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10902         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10903         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10904         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10905         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10906         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10907         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10908         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10909         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10910         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJK"
10911         "'>\n"
10912         "&en;"
10913         "</doc>";
10914 
10915   context_realloc_test(text);
10916 }
10917 END_TEST
10918 
START_TEST(test_nsalloc_realloc_long_context_3)10919 START_TEST(test_nsalloc_realloc_long_context_3) {
10920   const char *text
10921       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10922         "  <!ENTITY en SYSTEM 'bar'>\n"
10923         "]>\n"
10924         "<doc xmlns='http://example.org/"
10925         /* 64 characters per line */
10926         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10927         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
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/ABCDEFGH"
10942         "'>\n"
10943         "&en;"
10944         "</doc>";
10945 
10946   context_realloc_test(text);
10947 }
10948 END_TEST
10949 
START_TEST(test_nsalloc_realloc_long_context_4)10950 START_TEST(test_nsalloc_realloc_long_context_4) {
10951   const char *text
10952       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10953         "  <!ENTITY en SYSTEM 'bar'>\n"
10954         "]>\n"
10955         "<doc xmlns='http://example.org/"
10956         /* 64 characters per line */
10957         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10958         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
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"
10973         "'>\n"
10974         "&en;"
10975         "</doc>";
10976 
10977   context_realloc_test(text);
10978 }
10979 END_TEST
10980 
START_TEST(test_nsalloc_realloc_long_context_5)10981 START_TEST(test_nsalloc_realloc_long_context_5) {
10982   const char *text
10983       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10984         "  <!ENTITY en SYSTEM 'bar'>\n"
10985         "]>\n"
10986         "<doc xmlns='http://example.org/"
10987         /* 64 characters per line */
10988         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10989         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
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         "ABC"
11004         "'>\n"
11005         "&en;"
11006         "</doc>";
11007 
11008   context_realloc_test(text);
11009 }
11010 END_TEST
11011 
START_TEST(test_nsalloc_realloc_long_context_6)11012 START_TEST(test_nsalloc_realloc_long_context_6) {
11013   const char *text
11014       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11015         "  <!ENTITY en SYSTEM 'bar'>\n"
11016         "]>\n"
11017         "<doc xmlns='http://example.org/"
11018         /* 64 characters per line */
11019         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11020         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
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/ABCDEFGHIJKLMNOP"
11034         "'>\n"
11035         "&en;"
11036         "</doc>";
11037 
11038   context_realloc_test(text);
11039 }
11040 END_TEST
11041 
START_TEST(test_nsalloc_realloc_long_context_7)11042 START_TEST(test_nsalloc_realloc_long_context_7) {
11043   const char *text
11044       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11045         "  <!ENTITY en SYSTEM 'bar'>\n"
11046         "]>\n"
11047         "<doc xmlns='http://example.org/"
11048         /* 64 characters per line */
11049         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11050         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11051         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
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/ABCDEFGHIJKLM"
11065         "'>\n"
11066         "&en;"
11067         "</doc>";
11068 
11069   context_realloc_test(text);
11070 }
11071 END_TEST
11072 
START_TEST(test_nsalloc_realloc_long_ge_name)11073 START_TEST(test_nsalloc_realloc_long_ge_name) {
11074   const char *text
11075       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11076         "  <!ENTITY "
11077         /* 64 characters per line */
11078         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11079         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11080         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11081         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11082         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11083         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11084         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11085         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11086         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11087         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11088         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11089         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11090         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11091         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11092         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11093         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11094         " SYSTEM 'bar'>\n"
11095         "]>\n"
11096         "<doc xmlns='http://example.org/baz'>\n"
11097         "&"
11098         /* 64 characters per line */
11099         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11100         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11101         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11102         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11103         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11104         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11105         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11106         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11107         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11108         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11109         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11110         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11111         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11112         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11113         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11114         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11115         ";"
11116         "</doc>";
11117   ExtOption options[] = {
11118       {XCS("foo"), "<!ELEMENT el EMPTY>"}, {XCS("bar"), "<el/>"}, {NULL, NULL}};
11119   int i;
11120   const int max_realloc_count = 10;
11121 
11122   for (i = 0; i < max_realloc_count; i++) {
11123     reallocation_count = i;
11124     XML_SetUserData(g_parser, options);
11125     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11126     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11127     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
11128         != XML_STATUS_ERROR)
11129       break;
11130     /* See comment in test_nsalloc_xmlns() */
11131     nsalloc_teardown();
11132     nsalloc_setup();
11133   }
11134   if (i == 0)
11135     fail("Parsing worked despite failing reallocations");
11136   else if (i == max_realloc_count)
11137     fail("Parsing failed even at max reallocation count");
11138 }
11139 END_TEST
11140 
11141 /* Test that when a namespace is passed through the context mechanism
11142  * to an external entity parser, the parsers handle reallocation
11143  * failures correctly.  The prefix is exactly the right length to
11144  * provoke particular uncommon code paths.
11145  */
START_TEST(test_nsalloc_realloc_long_context_in_dtd)11146 START_TEST(test_nsalloc_realloc_long_context_in_dtd) {
11147   const char *text1
11148       = "<!DOCTYPE "
11149         /* 64 characters per line */
11150         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11151         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11152         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11153         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11154         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11155         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11156         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11157         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11158         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11159         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11160         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11161         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11162         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11163         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11164         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11165         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11166         ":doc [\n"
11167         "  <!ENTITY First SYSTEM 'foo/First'>\n"
11168         "]>\n"
11169         "<"
11170         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11171         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11172         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11173         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11174         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11175         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11176         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11177         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11178         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11179         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11180         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11181         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11182         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11183         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11184         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11185         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11186         ":doc xmlns:"
11187         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11188         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11189         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11190         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11191         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11192         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11193         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11194         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11195         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11196         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11197         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11198         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11199         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11200         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11201         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11202         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11203         "='foo/Second'>&First;";
11204   const char *text2
11205       = "</"
11206         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11207         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11208         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11209         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11210         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11211         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11212         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11213         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11214         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11215         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11216         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11217         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11218         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11219         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11220         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11221         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11222         ":doc>";
11223   ExtOption options[] = {{XCS("foo/First"), "Hello world"}, {NULL, NULL}};
11224   int i;
11225   const int max_realloc_count = 20;
11226 
11227   for (i = 0; i < max_realloc_count; i++) {
11228     reallocation_count = i;
11229     XML_SetUserData(g_parser, options);
11230     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11231     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11232     if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
11233             != XML_STATUS_ERROR
11234         && _XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2),
11235                                    XML_TRUE)
11236                != XML_STATUS_ERROR)
11237       break;
11238     /* See comment in test_nsalloc_xmlns() */
11239     nsalloc_teardown();
11240     nsalloc_setup();
11241   }
11242   if (i == 0)
11243     fail("Parsing worked despite failing reallocations");
11244   else if (i == max_realloc_count)
11245     fail("Parsing failed even at max reallocation count");
11246 }
11247 END_TEST
11248 
START_TEST(test_nsalloc_long_default_in_ext)11249 START_TEST(test_nsalloc_long_default_in_ext) {
11250   const char *text
11251       = "<!DOCTYPE doc [\n"
11252         "  <!ATTLIST e a1 CDATA '"
11253         /* 64 characters per line */
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         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11268         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11269         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11270         "'>\n"
11271         "  <!ENTITY x SYSTEM 'foo'>\n"
11272         "]>\n"
11273         "<doc>&x;</doc>";
11274   ExtOption options[] = {{XCS("foo"), "<e/>"}, {NULL, NULL}};
11275   int i;
11276   const int max_alloc_count = 50;
11277 
11278   for (i = 0; i < max_alloc_count; i++) {
11279     allocation_count = i;
11280     XML_SetUserData(g_parser, options);
11281     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11282     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11283     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
11284         != XML_STATUS_ERROR)
11285       break;
11286 
11287     /* See comment in test_nsalloc_xmlns() */
11288     nsalloc_teardown();
11289     nsalloc_setup();
11290   }
11291   if (i == 0)
11292     fail("Parsing worked despite failing allocations");
11293   else if (i == max_alloc_count)
11294     fail("Parsing failed even at max allocation count");
11295 }
11296 END_TEST
11297 
START_TEST(test_nsalloc_long_systemid_in_ext)11298 START_TEST(test_nsalloc_long_systemid_in_ext) {
11299   const char *text
11300       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11301         "  <!ENTITY en SYSTEM '"
11302         /* 64 characters per line */
11303         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11304         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11305         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11306         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11307         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11308         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11309         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11310         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11311         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11312         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11313         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11314         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11315         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11316         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11317         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11318         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11319         "'>\n"
11320         "]>\n"
11321         "<doc>&en;</doc>";
11322   ExtOption options[] = {
11323       {XCS("foo"), "<!ELEMENT e EMPTY>"},
11324       {/* clang-format off */
11325             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11326             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11327             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11328             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11329             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11330             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11331             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11332             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11333             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11334             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11335             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11336             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11337             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11338             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11339             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11340             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"),
11341        /* clang-format on */
11342        "<e/>"},
11343       {NULL, NULL}};
11344   int i;
11345   const int max_alloc_count = 55;
11346 
11347   for (i = 0; i < max_alloc_count; i++) {
11348     allocation_count = i;
11349     XML_SetUserData(g_parser, options);
11350     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11351     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11352     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
11353         != XML_STATUS_ERROR)
11354       break;
11355 
11356     /* See comment in test_nsalloc_xmlns() */
11357     nsalloc_teardown();
11358     nsalloc_setup();
11359   }
11360   if (i == 0)
11361     fail("Parsing worked despite failing allocations");
11362   else if (i == max_alloc_count)
11363     fail("Parsing failed even at max allocation count");
11364 }
11365 END_TEST
11366 
11367 /* Test the effects of allocation failure on parsing an element in a
11368  * namespace.  Based on test_nsalloc_long_context.
11369  */
START_TEST(test_nsalloc_prefixed_element)11370 START_TEST(test_nsalloc_prefixed_element) {
11371   const char *text = "<!DOCTYPE pfx:element SYSTEM 'foo' [\n"
11372                      "  <!ATTLIST pfx:element baz ID #REQUIRED>\n"
11373                      "  <!ENTITY en SYSTEM 'bar'>\n"
11374                      "]>\n"
11375                      "<pfx:element xmlns:pfx='http://example.org/' baz='2'>\n"
11376                      "&en;"
11377                      "</pfx:element>";
11378   ExtOption options[] = {
11379       {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}};
11380   int i;
11381   const int max_alloc_count = 70;
11382 
11383   for (i = 0; i < max_alloc_count; i++) {
11384     allocation_count = i;
11385     XML_SetUserData(g_parser, options);
11386     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11387     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11388     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
11389         != XML_STATUS_ERROR)
11390       break;
11391 
11392     /* See comment in test_nsalloc_xmlns() */
11393     nsalloc_teardown();
11394     nsalloc_setup();
11395   }
11396   if (i == 0)
11397     fail("Success despite failing allocator");
11398   else if (i == max_alloc_count)
11399     fail("Failed even at full allocation count");
11400 }
11401 END_TEST
11402 
11403 #if defined(XML_DTD)
11404 typedef enum XML_Status (*XmlParseFunction)(XML_Parser, const char *, int, int);
11405 
11406 struct AccountingTestCase {
11407   const char *primaryText;
11408   const char *firstExternalText;  /* often NULL */
11409   const char *secondExternalText; /* often NULL */
11410   const unsigned long long expectedCountBytesIndirectExtra;
11411   XML_Bool singleBytesWanted;
11412 };
11413 
11414 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)11415 accounting_external_entity_ref_handler(XML_Parser parser,
11416                                        const XML_Char *context,
11417                                        const XML_Char *base,
11418                                        const XML_Char *systemId,
11419                                        const XML_Char *publicId) {
11420   UNUSED_P(context);
11421   UNUSED_P(base);
11422   UNUSED_P(publicId);
11423 
11424   const struct AccountingTestCase *const testCase
11425       = (const struct AccountingTestCase *)XML_GetUserData(parser);
11426 
11427   const char *externalText = NULL;
11428   if (xcstrcmp(systemId, XCS("first.ent")) == 0) {
11429     externalText = testCase->firstExternalText;
11430   } else if (xcstrcmp(systemId, XCS("second.ent")) == 0) {
11431     externalText = testCase->secondExternalText;
11432   } else {
11433     assert(! "systemId is neither \"first.ent\" nor \"second.ent\"");
11434   }
11435   assert(externalText);
11436 
11437   XML_Parser entParser = XML_ExternalEntityParserCreate(parser, context, 0);
11438   assert(entParser);
11439 
11440   const XmlParseFunction xmlParseFunction
11441       = testCase->singleBytesWanted ? _XML_Parse_SINGLE_BYTES : XML_Parse;
11442 
11443   const enum XML_Status status = xmlParseFunction(
11444       entParser, externalText, (int)strlen(externalText), XML_TRUE);
11445 
11446   XML_ParserFree(entParser);
11447   return status;
11448 }
11449 
START_TEST(test_accounting_precision)11450 START_TEST(test_accounting_precision) {
11451   const XML_Bool filled_later = XML_TRUE; /* value is arbitrary */
11452   struct AccountingTestCase cases[] = {
11453       {"<e/>", NULL, NULL, 0, 0},
11454       {"<e></e>", NULL, NULL, 0, 0},
11455 
11456       /* Attributes */
11457       {"<e k1=\"v2\" k2=\"v2\"/>", NULL, NULL, 0, filled_later},
11458       {"<e k1=\"v2\" k2=\"v2\"></e>", NULL, NULL, 0, 0},
11459       {"<p:e xmlns:p=\"https://domain.invalid/\" />", NULL, NULL, 0,
11460        filled_later},
11461       {"<e k=\"&amp;&apos;&gt;&lt;&quot;\" />", NULL, NULL,
11462        sizeof(XML_Char) * 5 /* number of predefined entites */, filled_later},
11463       {"<e1 xmlns='https://example.org/'>\n"
11464        "  <e2 xmlns=''/>\n"
11465        "</e1>",
11466        NULL, NULL, 0, filled_later},
11467 
11468       /* Text */
11469       {"<e>text</e>", NULL, NULL, 0, filled_later},
11470       {"<e1><e2>text1<e3/>text2</e2></e1>", NULL, NULL, 0, filled_later},
11471       {"<e>&amp;&apos;&gt;&lt;&quot;</e>", NULL, NULL,
11472        sizeof(XML_Char) * 5 /* number of predefined entites */, filled_later},
11473       {"<e>&#65;&#41;</e>", NULL, NULL, 0, filled_later},
11474 
11475       /* Prolog */
11476       {"<?xml version=\"1.0\"?><root/>", NULL, NULL, 0, filled_later},
11477 
11478       /* Whitespace */
11479       {"  <e1>  <e2>  </e2>  </e1>  ", NULL, NULL, 0, filled_later},
11480       {"<e1  ><e2  /></e1  >", NULL, NULL, 0, filled_later},
11481       {"<e1><e2 k = \"v\"/><e3 k = 'v'/></e1>", NULL, NULL, 0, filled_later},
11482 
11483       /* Comments */
11484       {"<!-- Comment --><e><!-- Comment --></e>", NULL, NULL, 0, filled_later},
11485 
11486       /* Processing instructions */
11487       {"<?xml-stylesheet type=\"text/xsl\" href=\"https://domain.invalid/\" media=\"all\"?><e/>",
11488        NULL, NULL, 0, filled_later},
11489       {"<?pi0?><?pi1 ?><?pi2  ?><!DOCTYPE r SYSTEM 'first.ent'><r/>",
11490        "<?pi3?><!ENTITY % e1 SYSTEM 'second.ent'><?pi4?>%e1;<?pi5?>", "<?pi6?>",
11491        0, filled_later},
11492 
11493       /* CDATA */
11494       {"<e><![CDATA[one two three]]></e>", NULL, NULL, 0, filled_later},
11495       /* The following is the essence of this OSS-Fuzz finding:
11496          https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=34302
11497          https://oss-fuzz.com/testcase-detail/4860575394955264
11498       */
11499       {"<!DOCTYPE r [\n"
11500        "<!ENTITY e \"111<![CDATA[2 <= 2]]>333\">\n"
11501        "]>\n"
11502        "<r>&e;</r>\n",
11503        NULL, NULL, sizeof(XML_Char) * strlen("111<![CDATA[2 <= 2]]>333"),
11504        filled_later},
11505 
11506       /* Conditional sections */
11507       {"<!DOCTYPE r [\n"
11508        "<!ENTITY % draft 'INCLUDE'>\n"
11509        "<!ENTITY % final 'IGNORE'>\n"
11510        "<!ENTITY % import SYSTEM \"first.ent\">\n"
11511        "%import;\n"
11512        "]>\n"
11513        "<r/>\n",
11514        "<![%draft;[<!--1-->]]>\n"
11515        "<![%final;[<!--22-->]]>",
11516        NULL, sizeof(XML_Char) * (strlen("INCLUDE") + strlen("IGNORE")),
11517        filled_later},
11518 
11519       /* General entities */
11520       {"<!DOCTYPE root [\n"
11521        "<!ENTITY nine \"123456789\">\n"
11522        "]>\n"
11523        "<root>&nine;</root>",
11524        NULL, NULL, sizeof(XML_Char) * strlen("123456789"), filled_later},
11525       {"<!DOCTYPE root [\n"
11526        "<!ENTITY nine \"123456789\">\n"
11527        "]>\n"
11528        "<root k1=\"&nine;\"/>",
11529        NULL, NULL, sizeof(XML_Char) * strlen("123456789"), filled_later},
11530       {"<!DOCTYPE root [\n"
11531        "<!ENTITY nine \"123456789\">\n"
11532        "<!ENTITY nine2 \"&nine;&nine;\">\n"
11533        "]>\n"
11534        "<root>&nine2;&nine2;&nine2;</root>",
11535        NULL, NULL,
11536        sizeof(XML_Char) * 3 /* calls to &nine2; */ * 2 /* calls to &nine; */
11537            * (strlen("&nine;") + strlen("123456789")),
11538        filled_later},
11539       {"<!DOCTYPE r [\n"
11540        "  <!ENTITY five SYSTEM 'first.ent'>\n"
11541        "]>\n"
11542        "<r>&five;</r>",
11543        "12345", NULL, 0, filled_later},
11544 
11545       /* Parameter entities */
11546       {"<!DOCTYPE r [\n"
11547        "<!ENTITY % comment \"<!---->\">\n"
11548        "%comment;\n"
11549        "]>\n"
11550        "<r/>",
11551        NULL, NULL, sizeof(XML_Char) * strlen("<!---->"), filled_later},
11552       {"<!DOCTYPE r [\n"
11553        "<!ENTITY % ninedef \"&#60;!ENTITY nine &#34;123456789&#34;&#62;\">\n"
11554        "%ninedef;\n"
11555        "]>\n"
11556        "<r>&nine;</r>",
11557        NULL, NULL,
11558        sizeof(XML_Char)
11559            * (strlen("<!ENTITY nine \"123456789\">") + strlen("123456789")),
11560        filled_later},
11561       {"<!DOCTYPE r [\n"
11562        "<!ENTITY % comment \"<!--1-->\">\n"
11563        "<!ENTITY % comment2 \"&#37;comment;<!--22-->&#37;comment;\">\n"
11564        "%comment2;\n"
11565        "]>\n"
11566        "<r/>\n",
11567        NULL, NULL,
11568        sizeof(XML_Char)
11569            * (strlen("%comment;<!--22-->%comment;") + 2 * strlen("<!--1-->")),
11570        filled_later},
11571       {"<!DOCTYPE r [\n"
11572        "  <!ENTITY % five \"12345\">\n"
11573        "  <!ENTITY % five2def \"&#60;!ENTITY five2 &#34;[&#37;five;][&#37;five;]]]]&#34;&#62;\">\n"
11574        "  %five2def;\n"
11575        "]>\n"
11576        "<r>&five2;</r>",
11577        NULL, NULL, /* from "%five2def;": */
11578        sizeof(XML_Char)
11579            * (strlen("<!ENTITY five2 \"[%five;][%five;]]]]\">")
11580               + 2 /* calls to "%five;" */ * strlen("12345")
11581               + /* from "&five2;": */ strlen("[12345][12345]]]]")),
11582        filled_later},
11583       {"<!DOCTYPE r SYSTEM \"first.ent\">\n"
11584        "<r/>",
11585        "<!ENTITY % comment '<!--1-->'>\n"
11586        "<!ENTITY % comment2 '<!--22-->%comment;<!--22-->%comment;<!--22-->'>\n"
11587        "%comment2;",
11588        NULL,
11589        sizeof(XML_Char)
11590            * (strlen("<!--22-->%comment;<!--22-->%comment;<!--22-->")
11591               + 2 /* calls to "%comment;" */ * strlen("<!---->")),
11592        filled_later},
11593       {"<!DOCTYPE r SYSTEM 'first.ent'>\n"
11594        "<r/>",
11595        "<!ENTITY % e1 PUBLIC 'foo' 'second.ent'>\n"
11596        "<!ENTITY % e2 '<!--22-->%e1;<!--22-->'>\n"
11597        "%e2;\n",
11598        "<!--1-->", sizeof(XML_Char) * strlen("<!--22--><!--1--><!--22-->"),
11599        filled_later},
11600       {
11601           "<!DOCTYPE r SYSTEM 'first.ent'>\n"
11602           "<r/>",
11603           "<!ENTITY % e1 SYSTEM 'second.ent'>\n"
11604           "<!ENTITY % e2 '%e1;'>",
11605           "<?xml version='1.0' encoding='utf-8'?>\n"
11606           "hello\n"
11607           "xml" /* without trailing newline! */,
11608           0,
11609           filled_later,
11610       },
11611       {
11612           "<!DOCTYPE r SYSTEM 'first.ent'>\n"
11613           "<r/>",
11614           "<!ENTITY % e1 SYSTEM 'second.ent'>\n"
11615           "<!ENTITY % e2 '%e1;'>",
11616           "<?xml version='1.0' encoding='utf-8'?>\n"
11617           "hello\n"
11618           "xml\n" /* with trailing newline! */,
11619           0,
11620           filled_later,
11621       },
11622       {"<!DOCTYPE doc SYSTEM 'first.ent'>\n"
11623        "<doc></doc>\n",
11624        "<!ELEMENT doc EMPTY>\n"
11625        "<!ENTITY % e1 SYSTEM 'second.ent'>\n"
11626        "<!ENTITY % e2 '%e1;'>\n"
11627        "%e1;\n",
11628        "\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>" /* UTF-8 BOM */,
11629        strlen("\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>"), filled_later},
11630       {"<!DOCTYPE r [\n"
11631        "  <!ENTITY five SYSTEM 'first.ent'>\n"
11632        "]>\n"
11633        "<r>&five;</r>",
11634        "\xEF\xBB\xBF" /* UTF-8 BOM */, NULL, 0, filled_later},
11635   };
11636 
11637   const size_t countCases = sizeof(cases) / sizeof(cases[0]);
11638   size_t u = 0;
11639   for (; u < countCases; u++) {
11640     size_t v = 0;
11641     for (; v < 2; v++) {
11642       const XML_Bool singleBytesWanted = (v == 0) ? XML_FALSE : XML_TRUE;
11643       const unsigned long long expectedCountBytesDirect
11644           = strlen(cases[u].primaryText);
11645       const unsigned long long expectedCountBytesIndirect
11646           = (cases[u].firstExternalText ? strlen(cases[u].firstExternalText)
11647                                         : 0)
11648             + (cases[u].secondExternalText ? strlen(cases[u].secondExternalText)
11649                                            : 0)
11650             + cases[u].expectedCountBytesIndirectExtra;
11651 
11652       XML_Parser parser = XML_ParserCreate(NULL);
11653       XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11654       if (cases[u].firstExternalText) {
11655         XML_SetExternalEntityRefHandler(parser,
11656                                         accounting_external_entity_ref_handler);
11657         XML_SetUserData(parser, (void *)&cases[u]);
11658         cases[u].singleBytesWanted = singleBytesWanted;
11659       }
11660 
11661       const XmlParseFunction xmlParseFunction
11662           = singleBytesWanted ? _XML_Parse_SINGLE_BYTES : XML_Parse;
11663 
11664       enum XML_Status status
11665           = xmlParseFunction(parser, cases[u].primaryText,
11666                              (int)strlen(cases[u].primaryText), XML_TRUE);
11667       if (status != XML_STATUS_OK) {
11668         _xml_failure(parser, __FILE__, __LINE__);
11669       }
11670 
11671       const unsigned long long actualCountBytesDirect
11672           = testingAccountingGetCountBytesDirect(parser);
11673       const unsigned long long actualCountBytesIndirect
11674           = testingAccountingGetCountBytesIndirect(parser);
11675 
11676       XML_ParserFree(parser);
11677 
11678       if (actualCountBytesDirect != expectedCountBytesDirect) {
11679         fprintf(
11680             stderr,
11681             "Document " EXPAT_FMT_SIZE_T("") " of " EXPAT_FMT_SIZE_T("") ", %s: Expected " EXPAT_FMT_ULL(
11682                 "") " count direct bytes, got " EXPAT_FMT_ULL("") " instead.\n",
11683             u + 1, countCases, singleBytesWanted ? "single bytes" : "chunks",
11684             expectedCountBytesDirect, actualCountBytesDirect);
11685         fail("Count of direct bytes is off");
11686       }
11687 
11688       if (actualCountBytesIndirect != expectedCountBytesIndirect) {
11689         fprintf(
11690             stderr,
11691             "Document " EXPAT_FMT_SIZE_T("") " of " EXPAT_FMT_SIZE_T("") ", %s: Expected " EXPAT_FMT_ULL(
11692                 "") " count indirect bytes, got " EXPAT_FMT_ULL("") " instead.\n",
11693             u + 1, countCases, singleBytesWanted ? "single bytes" : "chunks",
11694             expectedCountBytesIndirect, actualCountBytesIndirect);
11695         fail("Count of indirect bytes is off");
11696       }
11697     }
11698   }
11699 }
11700 END_TEST
11701 
START_TEST(test_billion_laughs_attack_protection_api)11702 START_TEST(test_billion_laughs_attack_protection_api) {
11703   XML_Parser parserWithoutParent = XML_ParserCreate(NULL);
11704   XML_Parser parserWithParent
11705       = XML_ExternalEntityParserCreate(parserWithoutParent, NULL, NULL);
11706   if (parserWithoutParent == NULL)
11707     fail("parserWithoutParent is NULL");
11708   if (parserWithParent == NULL)
11709     fail("parserWithParent is NULL");
11710 
11711   // XML_SetBillionLaughsAttackProtectionMaximumAmplification, error cases
11712   if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(NULL, 123.0f)
11713       == XML_TRUE)
11714     fail("Call with NULL parser is NOT supposed to succeed");
11715   if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(parserWithParent,
11716                                                                123.0f)
11717       == XML_TRUE)
11718     fail("Call with non-root parser is NOT supposed to succeed");
11719   if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
11720           parserWithoutParent, NAN)
11721       == XML_TRUE)
11722     fail("Call with NaN limit is NOT supposed to succeed");
11723   if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
11724           parserWithoutParent, -1.0f)
11725       == XML_TRUE)
11726     fail("Call with negative limit is NOT supposed to succeed");
11727   if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
11728           parserWithoutParent, 0.9f)
11729       == XML_TRUE)
11730     fail("Call with positive limit <1.0 is NOT supposed to succeed");
11731 
11732   // XML_SetBillionLaughsAttackProtectionMaximumAmplification, success cases
11733   if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
11734           parserWithoutParent, 1.0f)
11735       == XML_FALSE)
11736     fail("Call with positive limit >=1.0 is supposed to succeed");
11737   if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
11738           parserWithoutParent, 123456.789f)
11739       == XML_FALSE)
11740     fail("Call with positive limit >=1.0 is supposed to succeed");
11741   if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
11742           parserWithoutParent, INFINITY)
11743       == XML_FALSE)
11744     fail("Call with positive limit >=1.0 is supposed to succeed");
11745 
11746   // XML_SetBillionLaughsAttackProtectionActivationThreshold, error cases
11747   if (XML_SetBillionLaughsAttackProtectionActivationThreshold(NULL, 123)
11748       == XML_TRUE)
11749     fail("Call with NULL parser is NOT supposed to succeed");
11750   if (XML_SetBillionLaughsAttackProtectionActivationThreshold(parserWithParent,
11751                                                               123)
11752       == XML_TRUE)
11753     fail("Call with non-root parser is NOT supposed to succeed");
11754 
11755   // XML_SetBillionLaughsAttackProtectionActivationThreshold, success cases
11756   if (XML_SetBillionLaughsAttackProtectionActivationThreshold(
11757           parserWithoutParent, 123)
11758       == XML_FALSE)
11759     fail("Call with non-NULL parentless parser is supposed to succeed");
11760 
11761   XML_ParserFree(parserWithParent);
11762   XML_ParserFree(parserWithoutParent);
11763 }
11764 END_TEST
11765 
START_TEST(test_helper_unsigned_char_to_printable)11766 START_TEST(test_helper_unsigned_char_to_printable) {
11767   // Smoke test
11768   unsigned char uc = 0;
11769   for (; uc < (unsigned char)-1; uc++) {
11770     const char *const printable = unsignedCharToPrintable(uc);
11771     if (printable == NULL)
11772       fail("unsignedCharToPrintable returned NULL");
11773     if (strlen(printable) < (size_t)1)
11774       fail("unsignedCharToPrintable returned empty string");
11775   }
11776 
11777   // Two concrete samples
11778   if (strcmp(unsignedCharToPrintable('A'), "A") != 0)
11779     fail("unsignedCharToPrintable result mistaken");
11780   if (strcmp(unsignedCharToPrintable('\\'), "\\\\") != 0)
11781     fail("unsignedCharToPrintable result mistaken");
11782 }
11783 END_TEST
11784 
START_TEST(test_amplification_isolated_external_parser)11785 START_TEST(test_amplification_isolated_external_parser) {
11786   // NOTE: Length 44 is precisely twice the length of "<!ENTITY a SYSTEM 'b'>"
11787   // (22) that is used in function accountingGetCurrentAmplification in
11788   // xmlparse.c.
11789   //                  1.........1.........1.........1.........1..4 => 44
11790   const char doc[] = "<!ENTITY % p1 '123456789_123456789_1234567'>";
11791   const int docLen = (int)sizeof(doc) - 1;
11792   const float maximumToleratedAmplification = 2.0f;
11793 
11794   struct TestCase {
11795     int offsetOfThreshold;
11796     enum XML_Status expectedStatus;
11797   };
11798 
11799   struct TestCase cases[] = {
11800       {-2, XML_STATUS_ERROR}, {-1, XML_STATUS_ERROR}, {0, XML_STATUS_ERROR},
11801       {+1, XML_STATUS_OK},    {+2, XML_STATUS_OK},
11802   };
11803 
11804   for (size_t i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) {
11805     const int offsetOfThreshold = cases[i].offsetOfThreshold;
11806     const enum XML_Status expectedStatus = cases[i].expectedStatus;
11807     const unsigned long long activationThresholdBytes
11808         = docLen + offsetOfThreshold;
11809 
11810     set_subtest("offsetOfThreshold=%d, expectedStatus=%d", offsetOfThreshold,
11811                 expectedStatus);
11812 
11813     XML_Parser parser = XML_ParserCreate(NULL);
11814     assert_true(parser != NULL);
11815 
11816     assert_true(XML_SetBillionLaughsAttackProtectionMaximumAmplification(
11817                     parser, maximumToleratedAmplification)
11818                 == XML_TRUE);
11819     assert_true(XML_SetBillionLaughsAttackProtectionActivationThreshold(
11820                     parser, activationThresholdBytes)
11821                 == XML_TRUE);
11822 
11823     XML_Parser ext_parser = XML_ExternalEntityParserCreate(parser, NULL, NULL);
11824     assert_true(ext_parser != NULL);
11825 
11826     const enum XML_Status actualStatus
11827         = _XML_Parse_SINGLE_BYTES(ext_parser, doc, docLen, XML_TRUE);
11828 
11829     assert_true(actualStatus == expectedStatus);
11830     if (actualStatus != XML_STATUS_OK) {
11831       assert_true(XML_GetErrorCode(ext_parser)
11832                   == XML_ERROR_AMPLIFICATION_LIMIT_BREACH);
11833     }
11834 
11835     XML_ParserFree(ext_parser);
11836     XML_ParserFree(parser);
11837   }
11838 }
11839 END_TEST
11840 
11841 #endif // defined(XML_DTD)
11842 
11843 static Suite *
make_suite(void)11844 make_suite(void) {
11845   Suite *s = suite_create("basic");
11846   TCase *tc_basic = tcase_create("basic tests");
11847   TCase *tc_namespace = tcase_create("XML namespaces");
11848   TCase *tc_misc = tcase_create("miscellaneous tests");
11849   TCase *tc_alloc = tcase_create("allocation tests");
11850   TCase *tc_nsalloc = tcase_create("namespace allocation tests");
11851 #if defined(XML_DTD)
11852   TCase *tc_accounting = tcase_create("accounting tests");
11853 #endif
11854 
11855   suite_add_tcase(s, tc_basic);
11856   tcase_add_checked_fixture(tc_basic, basic_setup, basic_teardown);
11857   tcase_add_test(tc_basic, test_nul_byte);
11858   tcase_add_test(tc_basic, test_u0000_char);
11859   tcase_add_test(tc_basic, test_siphash_self);
11860   tcase_add_test(tc_basic, test_siphash_spec);
11861   tcase_add_test(tc_basic, test_bom_utf8);
11862   tcase_add_test(tc_basic, test_bom_utf16_be);
11863   tcase_add_test(tc_basic, test_bom_utf16_le);
11864   tcase_add_test(tc_basic, test_nobom_utf16_le);
11865   tcase_add_test(tc_basic, test_illegal_utf8);
11866   tcase_add_test(tc_basic, test_utf8_auto_align);
11867   tcase_add_test(tc_basic, test_utf16);
11868   tcase_add_test(tc_basic, test_utf16_le_epilog_newline);
11869   tcase_add_test(tc_basic, test_not_utf16);
11870   tcase_add_test(tc_basic, test_bad_encoding);
11871   tcase_add_test(tc_basic, test_latin1_umlauts);
11872   tcase_add_test(tc_basic, test_long_utf8_character);
11873   tcase_add_test(tc_basic, test_long_latin1_attribute);
11874   tcase_add_test(tc_basic, test_long_ascii_attribute);
11875   /* Regression test for SF bug #491986. */
11876   tcase_add_test(tc_basic, test_danish_latin1);
11877   /* Regression test for SF bug #514281. */
11878   tcase_add_test(tc_basic, test_french_charref_hexidecimal);
11879   tcase_add_test(tc_basic, test_french_charref_decimal);
11880   tcase_add_test(tc_basic, test_french_latin1);
11881   tcase_add_test(tc_basic, test_french_utf8);
11882   tcase_add_test(tc_basic, test_utf8_false_rejection);
11883   tcase_add_test(tc_basic, test_line_number_after_parse);
11884   tcase_add_test(tc_basic, test_column_number_after_parse);
11885   tcase_add_test(tc_basic, test_line_and_column_numbers_inside_handlers);
11886   tcase_add_test(tc_basic, test_line_number_after_error);
11887   tcase_add_test(tc_basic, test_column_number_after_error);
11888   tcase_add_test(tc_basic, test_really_long_lines);
11889   tcase_add_test(tc_basic, test_really_long_encoded_lines);
11890   tcase_add_test(tc_basic, test_end_element_events);
11891   tcase_add_test(tc_basic, test_attr_whitespace_normalization);
11892   tcase_add_test(tc_basic, test_xmldecl_misplaced);
11893   tcase_add_test(tc_basic, test_xmldecl_invalid);
11894   tcase_add_test(tc_basic, test_xmldecl_missing_attr);
11895   tcase_add_test(tc_basic, test_xmldecl_missing_value);
11896   tcase_add_test(tc_basic, test_unknown_encoding_internal_entity);
11897   tcase_add_test(tc_basic, test_unrecognised_encoding_internal_entity);
11898   tcase_add_test(tc_basic, test_wfc_undeclared_entity_unread_external_subset);
11899   tcase_add_test(tc_basic, test_wfc_undeclared_entity_no_external_subset);
11900   tcase_add_test(tc_basic, test_wfc_undeclared_entity_standalone);
11901   tcase_add_test(tc_basic, test_wfc_undeclared_entity_with_external_subset);
11902   tcase_add_test(tc_basic, test_not_standalone_handler_reject);
11903   tcase_add_test(tc_basic, test_not_standalone_handler_accept);
11904   tcase_add_test(tc_basic,
11905                  test_wfc_undeclared_entity_with_external_subset_standalone);
11906   tcase_add_test(tc_basic, test_entity_with_external_subset_unless_standalone);
11907   tcase_add_test(tc_basic, test_wfc_no_recursive_entity_refs);
11908   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_set_encoding);
11909   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_no_handler);
11910   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_set_bom);
11911   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_bad_encoding);
11912   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_bad_encoding_2);
11913   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_invalid_parse);
11914   tcase_add_test__ifdef_xml_dtd(tc_basic,
11915                                 test_ext_entity_invalid_suspended_parse);
11916   tcase_add_test(tc_basic, test_dtd_default_handling);
11917   tcase_add_test(tc_basic, test_dtd_attr_handling);
11918   tcase_add_test(tc_basic, test_empty_ns_without_namespaces);
11919   tcase_add_test(tc_basic, test_ns_in_attribute_default_without_namespaces);
11920   tcase_add_test(tc_basic, test_stop_parser_between_char_data_calls);
11921   tcase_add_test(tc_basic, test_suspend_parser_between_char_data_calls);
11922   tcase_add_test(tc_basic, test_repeated_stop_parser_between_char_data_calls);
11923   tcase_add_test(tc_basic, test_good_cdata_ascii);
11924   tcase_add_test(tc_basic, test_good_cdata_utf16);
11925   tcase_add_test(tc_basic, test_good_cdata_utf16_le);
11926   tcase_add_test(tc_basic, test_long_cdata_utf16);
11927   tcase_add_test(tc_basic, test_multichar_cdata_utf16);
11928   tcase_add_test(tc_basic, test_utf16_bad_surrogate_pair);
11929   tcase_add_test(tc_basic, test_bad_cdata);
11930   tcase_add_test(tc_basic, test_bad_cdata_utf16);
11931   tcase_add_test(tc_basic, test_stop_parser_between_cdata_calls);
11932   tcase_add_test(tc_basic, test_suspend_parser_between_cdata_calls);
11933   tcase_add_test(tc_basic, test_memory_allocation);
11934   tcase_add_test(tc_basic, test_default_current);
11935   tcase_add_test(tc_basic, test_dtd_elements);
11936   tcase_add_test__ifdef_xml_dtd(tc_basic, test_set_foreign_dtd);
11937   tcase_add_test__ifdef_xml_dtd(tc_basic, test_foreign_dtd_not_standalone);
11938   tcase_add_test__ifdef_xml_dtd(tc_basic, test_invalid_foreign_dtd);
11939   tcase_add_test__ifdef_xml_dtd(tc_basic, test_foreign_dtd_with_doctype);
11940   tcase_add_test__ifdef_xml_dtd(tc_basic,
11941                                 test_foreign_dtd_without_external_subset);
11942   tcase_add_test__ifdef_xml_dtd(tc_basic, test_empty_foreign_dtd);
11943   tcase_add_test(tc_basic, test_set_base);
11944   tcase_add_test(tc_basic, test_attributes);
11945   tcase_add_test(tc_basic, test_reset_in_entity);
11946   tcase_add_test(tc_basic, test_resume_invalid_parse);
11947   tcase_add_test(tc_basic, test_resume_resuspended);
11948   tcase_add_test(tc_basic, test_cdata_default);
11949   tcase_add_test(tc_basic, test_subordinate_reset);
11950   tcase_add_test(tc_basic, test_subordinate_suspend);
11951   tcase_add_test(tc_basic, test_subordinate_xdecl_suspend);
11952   tcase_add_test(tc_basic, test_subordinate_xdecl_abort);
11953   tcase_add_test(tc_basic, test_explicit_encoding);
11954   tcase_add_test(tc_basic, test_trailing_cr);
11955   tcase_add_test(tc_basic, test_ext_entity_trailing_cr);
11956   tcase_add_test(tc_basic, test_trailing_rsqb);
11957   tcase_add_test(tc_basic, test_ext_entity_trailing_rsqb);
11958   tcase_add_test(tc_basic, test_ext_entity_good_cdata);
11959   tcase_add_test__ifdef_xml_dtd(tc_basic, test_user_parameters);
11960   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_ref_parameter);
11961   tcase_add_test(tc_basic, test_empty_parse);
11962   tcase_add_test(tc_basic, test_negative_len_parse);
11963   tcase_add_test(tc_basic, test_negative_len_parse_buffer);
11964   tcase_add_test(tc_basic, test_get_buffer_1);
11965   tcase_add_test(tc_basic, test_get_buffer_2);
11966   tcase_add_test(tc_basic, test_byte_info_at_end);
11967   tcase_add_test(tc_basic, test_byte_info_at_error);
11968   tcase_add_test(tc_basic, test_byte_info_at_cdata);
11969   tcase_add_test(tc_basic, test_predefined_entities);
11970   tcase_add_test__ifdef_xml_dtd(tc_basic, test_invalid_tag_in_dtd);
11971   tcase_add_test(tc_basic, test_not_predefined_entities);
11972   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section);
11973   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section_utf16);
11974   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section_utf16_be);
11975   tcase_add_test__ifdef_xml_dtd(tc_basic, test_bad_ignore_section);
11976   tcase_add_test__ifdef_xml_dtd(tc_basic, test_external_entity_values);
11977   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_not_standalone);
11978   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_value_abort);
11979   tcase_add_test(tc_basic, test_bad_public_doctype);
11980   tcase_add_test(tc_basic, test_attribute_enum_value);
11981   tcase_add_test(tc_basic, test_predefined_entity_redefinition);
11982   tcase_add_test__ifdef_xml_dtd(tc_basic, test_dtd_stop_processing);
11983   tcase_add_test(tc_basic, test_public_notation_no_sysid);
11984   tcase_add_test(tc_basic, test_nested_groups);
11985   tcase_add_test(tc_basic, test_group_choice);
11986   tcase_add_test(tc_basic, test_standalone_parameter_entity);
11987   tcase_add_test__ifdef_xml_dtd(tc_basic, test_skipped_parameter_entity);
11988   tcase_add_test__ifdef_xml_dtd(tc_basic,
11989                                 test_recursive_external_parameter_entity);
11990   tcase_add_test(tc_basic, test_undefined_ext_entity_in_external_dtd);
11991   tcase_add_test(tc_basic, test_suspend_xdecl);
11992   tcase_add_test(tc_basic, test_abort_epilog);
11993   tcase_add_test(tc_basic, test_abort_epilog_2);
11994   tcase_add_test(tc_basic, test_suspend_epilog);
11995   tcase_add_test(tc_basic, test_suspend_in_sole_empty_tag);
11996   tcase_add_test(tc_basic, test_unfinished_epilog);
11997   tcase_add_test(tc_basic, test_partial_char_in_epilog);
11998   tcase_add_test(tc_basic, test_hash_collision);
11999   tcase_add_test__ifdef_xml_dtd(tc_basic, test_suspend_resume_internal_entity);
12000   tcase_add_test__ifdef_xml_dtd(tc_basic,
12001                                 test_suspend_resume_internal_entity_issue_629);
12002   tcase_add_test__ifdef_xml_dtd(tc_basic, test_resume_entity_with_syntax_error);
12003   tcase_add_test__ifdef_xml_dtd(tc_basic, test_suspend_resume_parameter_entity);
12004   tcase_add_test(tc_basic, test_restart_on_error);
12005   tcase_add_test(tc_basic, test_reject_lt_in_attribute_value);
12006   tcase_add_test(tc_basic, test_reject_unfinished_param_in_att_value);
12007   tcase_add_test(tc_basic, test_trailing_cr_in_att_value);
12008   tcase_add_test(tc_basic, test_standalone_internal_entity);
12009   tcase_add_test(tc_basic, test_skipped_external_entity);
12010   tcase_add_test(tc_basic, test_skipped_null_loaded_ext_entity);
12011   tcase_add_test(tc_basic, test_skipped_unloaded_ext_entity);
12012   tcase_add_test__ifdef_xml_dtd(tc_basic, test_param_entity_with_trailing_cr);
12013   tcase_add_test(tc_basic, test_invalid_character_entity);
12014   tcase_add_test(tc_basic, test_invalid_character_entity_2);
12015   tcase_add_test(tc_basic, test_invalid_character_entity_3);
12016   tcase_add_test(tc_basic, test_invalid_character_entity_4);
12017   tcase_add_test(tc_basic, test_pi_handled_in_default);
12018   tcase_add_test(tc_basic, test_comment_handled_in_default);
12019   tcase_add_test(tc_basic, test_pi_yml);
12020   tcase_add_test(tc_basic, test_pi_xnl);
12021   tcase_add_test(tc_basic, test_pi_xmm);
12022   tcase_add_test(tc_basic, test_utf16_pi);
12023   tcase_add_test(tc_basic, test_utf16_be_pi);
12024   tcase_add_test(tc_basic, test_utf16_be_comment);
12025   tcase_add_test(tc_basic, test_utf16_le_comment);
12026   tcase_add_test(tc_basic, test_missing_encoding_conversion_fn);
12027   tcase_add_test(tc_basic, test_failing_encoding_conversion_fn);
12028   tcase_add_test(tc_basic, test_unknown_encoding_success);
12029   tcase_add_test(tc_basic, test_unknown_encoding_bad_name);
12030   tcase_add_test(tc_basic, test_unknown_encoding_bad_name_2);
12031   tcase_add_test(tc_basic, test_unknown_encoding_long_name_1);
12032   tcase_add_test(tc_basic, test_unknown_encoding_long_name_2);
12033   tcase_add_test(tc_basic, test_invalid_unknown_encoding);
12034   tcase_add_test(tc_basic, test_unknown_ascii_encoding_ok);
12035   tcase_add_test(tc_basic, test_unknown_ascii_encoding_fail);
12036   tcase_add_test(tc_basic, test_unknown_encoding_invalid_length);
12037   tcase_add_test(tc_basic, test_unknown_encoding_invalid_topbit);
12038   tcase_add_test(tc_basic, test_unknown_encoding_invalid_surrogate);
12039   tcase_add_test(tc_basic, test_unknown_encoding_invalid_high);
12040   tcase_add_test(tc_basic, test_unknown_encoding_invalid_attr_value);
12041   tcase_add_test(tc_basic, test_ext_entity_latin1_utf16le_bom);
12042   tcase_add_test(tc_basic, test_ext_entity_latin1_utf16be_bom);
12043   tcase_add_test(tc_basic, test_ext_entity_latin1_utf16le_bom2);
12044   tcase_add_test(tc_basic, test_ext_entity_latin1_utf16be_bom2);
12045   tcase_add_test(tc_basic, test_ext_entity_utf16_be);
12046   tcase_add_test(tc_basic, test_ext_entity_utf16_le);
12047   tcase_add_test(tc_basic, test_ext_entity_utf16_unknown);
12048   tcase_add_test(tc_basic, test_ext_entity_utf8_non_bom);
12049   tcase_add_test(tc_basic, test_utf8_in_cdata_section);
12050   tcase_add_test(tc_basic, test_utf8_in_cdata_section_2);
12051   tcase_add_test(tc_basic, test_trailing_spaces_in_elements);
12052   tcase_add_test(tc_basic, test_utf16_attribute);
12053   tcase_add_test(tc_basic, test_utf16_second_attr);
12054   tcase_add_test(tc_basic, test_attr_after_solidus);
12055   tcase_add_test__ifdef_xml_dtd(tc_basic, test_utf16_pe);
12056   tcase_add_test(tc_basic, test_bad_attr_desc_keyword);
12057   tcase_add_test(tc_basic, test_bad_attr_desc_keyword_utf16);
12058   tcase_add_test(tc_basic, test_bad_doctype);
12059   tcase_add_test(tc_basic, test_bad_doctype_utf16);
12060   tcase_add_test(tc_basic, test_bad_doctype_plus);
12061   tcase_add_test(tc_basic, test_bad_doctype_star);
12062   tcase_add_test(tc_basic, test_bad_doctype_query);
12063   tcase_add_test__ifdef_xml_dtd(tc_basic, test_unknown_encoding_bad_ignore);
12064   tcase_add_test(tc_basic, test_entity_in_utf16_be_attr);
12065   tcase_add_test(tc_basic, test_entity_in_utf16_le_attr);
12066   tcase_add_test__ifdef_xml_dtd(tc_basic, test_entity_public_utf16_be);
12067   tcase_add_test__ifdef_xml_dtd(tc_basic, test_entity_public_utf16_le);
12068   tcase_add_test(tc_basic, test_short_doctype);
12069   tcase_add_test(tc_basic, test_short_doctype_2);
12070   tcase_add_test(tc_basic, test_short_doctype_3);
12071   tcase_add_test(tc_basic, test_long_doctype);
12072   tcase_add_test(tc_basic, test_bad_entity);
12073   tcase_add_test(tc_basic, test_bad_entity_2);
12074   tcase_add_test(tc_basic, test_bad_entity_3);
12075   tcase_add_test(tc_basic, test_bad_entity_4);
12076   tcase_add_test(tc_basic, test_bad_notation);
12077   tcase_add_test(tc_basic, test_default_doctype_handler);
12078   tcase_add_test(tc_basic, test_empty_element_abort);
12079 
12080   suite_add_tcase(s, tc_namespace);
12081   tcase_add_checked_fixture(tc_namespace, namespace_setup, namespace_teardown);
12082   tcase_add_test(tc_namespace, test_return_ns_triplet);
12083   tcase_add_test(tc_namespace, test_ns_tagname_overwrite);
12084   tcase_add_test(tc_namespace, test_ns_tagname_overwrite_triplet);
12085   tcase_add_test(tc_namespace, test_start_ns_clears_start_element);
12086   tcase_add_test__ifdef_xml_dtd(tc_namespace,
12087                                 test_default_ns_from_ext_subset_and_ext_ge);
12088   tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_1);
12089   tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_2);
12090   tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_3);
12091   tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_4);
12092   tcase_add_test(tc_namespace, test_ns_unbound_prefix);
12093   tcase_add_test(tc_namespace, test_ns_default_with_empty_uri);
12094   tcase_add_test(tc_namespace, test_ns_duplicate_attrs_diff_prefixes);
12095   tcase_add_test(tc_namespace, test_ns_duplicate_hashes);
12096   tcase_add_test(tc_namespace, test_ns_unbound_prefix_on_attribute);
12097   tcase_add_test(tc_namespace, test_ns_unbound_prefix_on_element);
12098   tcase_add_test(tc_namespace, test_ns_parser_reset);
12099   tcase_add_test(tc_namespace, test_ns_long_element);
12100   tcase_add_test(tc_namespace, test_ns_mixed_prefix_atts);
12101   tcase_add_test(tc_namespace, test_ns_extend_uri_buffer);
12102   tcase_add_test(tc_namespace, test_ns_reserved_attributes);
12103   tcase_add_test(tc_namespace, test_ns_reserved_attributes_2);
12104   tcase_add_test(tc_namespace, test_ns_extremely_long_prefix);
12105   tcase_add_test(tc_namespace, test_ns_unknown_encoding_success);
12106   tcase_add_test(tc_namespace, test_ns_double_colon);
12107   tcase_add_test(tc_namespace, test_ns_double_colon_element);
12108   tcase_add_test(tc_namespace, test_ns_bad_attr_leafname);
12109   tcase_add_test(tc_namespace, test_ns_bad_element_leafname);
12110   tcase_add_test(tc_namespace, test_ns_utf16_leafname);
12111   tcase_add_test(tc_namespace, test_ns_utf16_element_leafname);
12112   tcase_add_test(tc_namespace, test_ns_utf16_doctype);
12113   tcase_add_test(tc_namespace, test_ns_invalid_doctype);
12114   tcase_add_test(tc_namespace, test_ns_double_colon_doctype);
12115 
12116   suite_add_tcase(s, tc_misc);
12117   tcase_add_checked_fixture(tc_misc, NULL, basic_teardown);
12118   tcase_add_test(tc_misc, test_misc_alloc_create_parser);
12119   tcase_add_test(tc_misc, test_misc_alloc_create_parser_with_encoding);
12120   tcase_add_test(tc_misc, test_misc_null_parser);
12121   tcase_add_test(tc_misc, test_misc_error_string);
12122   tcase_add_test(tc_misc, test_misc_version);
12123   tcase_add_test(tc_misc, test_misc_features);
12124   tcase_add_test(tc_misc, test_misc_attribute_leak);
12125   tcase_add_test(tc_misc, test_misc_utf16le);
12126   tcase_add_test(tc_misc, test_misc_stop_during_end_handler_issue_240_1);
12127   tcase_add_test(tc_misc, test_misc_stop_during_end_handler_issue_240_2);
12128   tcase_add_test__ifdef_xml_dtd(
12129       tc_misc, test_misc_deny_internal_entity_closing_doctype_issue_317);
12130 
12131   suite_add_tcase(s, tc_alloc);
12132   tcase_add_checked_fixture(tc_alloc, alloc_setup, alloc_teardown);
12133   tcase_add_test(tc_alloc, test_alloc_parse_xdecl);
12134   tcase_add_test(tc_alloc, test_alloc_parse_xdecl_2);
12135   tcase_add_test(tc_alloc, test_alloc_parse_pi);
12136   tcase_add_test(tc_alloc, test_alloc_parse_pi_2);
12137   tcase_add_test(tc_alloc, test_alloc_parse_pi_3);
12138   tcase_add_test(tc_alloc, test_alloc_parse_comment);
12139   tcase_add_test(tc_alloc, test_alloc_parse_comment_2);
12140   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_create_external_parser);
12141   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_run_external_parser);
12142   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_dtd_copy_default_atts);
12143   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_external_entity);
12144   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_ext_entity_set_encoding);
12145   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_internal_entity);
12146   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_dtd_default_handling);
12147   tcase_add_test(tc_alloc, test_alloc_explicit_encoding);
12148   tcase_add_test(tc_alloc, test_alloc_set_base);
12149   tcase_add_test(tc_alloc, test_alloc_realloc_buffer);
12150   tcase_add_test(tc_alloc, test_alloc_ext_entity_realloc_buffer);
12151   tcase_add_test(tc_alloc, test_alloc_realloc_many_attributes);
12152   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_public_entity_value);
12153   tcase_add_test__ifdef_xml_dtd(tc_alloc,
12154                                 test_alloc_realloc_subst_public_entity_value);
12155   tcase_add_test(tc_alloc, test_alloc_parse_public_doctype);
12156   tcase_add_test(tc_alloc, test_alloc_parse_public_doctype_long_name);
12157   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_set_foreign_dtd);
12158   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_attribute_enum_value);
12159   tcase_add_test__ifdef_xml_dtd(tc_alloc,
12160                                 test_alloc_realloc_attribute_enum_value);
12161   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_implied_attribute);
12162   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_default_attribute);
12163   tcase_add_test(tc_alloc, test_alloc_notation);
12164   tcase_add_test(tc_alloc, test_alloc_public_notation);
12165   tcase_add_test(tc_alloc, test_alloc_system_notation);
12166   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_nested_groups);
12167   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_nested_groups);
12168   tcase_add_test(tc_alloc, test_alloc_large_group);
12169   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_group_choice);
12170   tcase_add_test(tc_alloc, test_alloc_pi_in_epilog);
12171   tcase_add_test(tc_alloc, test_alloc_comment_in_epilog);
12172   tcase_add_test__ifdef_xml_dtd(tc_alloc,
12173                                 test_alloc_realloc_long_attribute_value);
12174   tcase_add_test(tc_alloc, test_alloc_attribute_whitespace);
12175   tcase_add_test(tc_alloc, test_alloc_attribute_predefined_entity);
12176   tcase_add_test(tc_alloc, test_alloc_long_attr_default_with_char_ref);
12177   tcase_add_test(tc_alloc, test_alloc_long_attr_value);
12178   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_nested_entities);
12179   tcase_add_test__ifdef_xml_dtd(tc_alloc,
12180                                 test_alloc_realloc_param_entity_newline);
12181   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_ce_extends_pe);
12182   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_attributes);
12183   tcase_add_test(tc_alloc, test_alloc_long_doc_name);
12184   tcase_add_test(tc_alloc, test_alloc_long_base);
12185   tcase_add_test(tc_alloc, test_alloc_long_public_id);
12186   tcase_add_test(tc_alloc, test_alloc_long_entity_value);
12187   tcase_add_test(tc_alloc, test_alloc_long_notation);
12188   tcase_add_test__ifdef_xml_dtd(
12189       tc_alloc, test_alloc_reset_after_external_entity_parser_create_fail);
12190 
12191   suite_add_tcase(s, tc_nsalloc);
12192   tcase_add_checked_fixture(tc_nsalloc, nsalloc_setup, nsalloc_teardown);
12193   tcase_add_test(tc_nsalloc, test_nsalloc_xmlns);
12194   tcase_add_test(tc_nsalloc, test_nsalloc_parse_buffer);
12195   tcase_add_test(tc_nsalloc, test_nsalloc_long_prefix);
12196   tcase_add_test(tc_nsalloc, test_nsalloc_long_uri);
12197   tcase_add_test(tc_nsalloc, test_nsalloc_long_attr);
12198   tcase_add_test(tc_nsalloc, test_nsalloc_long_attr_prefix);
12199   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_attributes);
12200   tcase_add_test(tc_nsalloc, test_nsalloc_long_element);
12201   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_binding_uri);
12202   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_prefix);
12203   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_longer_prefix);
12204   tcase_add_test(tc_nsalloc, test_nsalloc_long_namespace);
12205   tcase_add_test(tc_nsalloc, test_nsalloc_less_long_namespace);
12206   tcase_add_test(tc_nsalloc, test_nsalloc_long_context);
12207   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context);
12208   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_2);
12209   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_3);
12210   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_4);
12211   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_5);
12212   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_6);
12213   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_7);
12214   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_ge_name);
12215   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_in_dtd);
12216   tcase_add_test(tc_nsalloc, test_nsalloc_long_default_in_ext);
12217   tcase_add_test(tc_nsalloc, test_nsalloc_long_systemid_in_ext);
12218   tcase_add_test(tc_nsalloc, test_nsalloc_prefixed_element);
12219 
12220 #if defined(XML_DTD)
12221   suite_add_tcase(s, tc_accounting);
12222   tcase_add_test(tc_accounting, test_accounting_precision);
12223   tcase_add_test(tc_accounting, test_billion_laughs_attack_protection_api);
12224   tcase_add_test(tc_accounting, test_helper_unsigned_char_to_printable);
12225   tcase_add_test__ifdef_xml_dtd(tc_accounting,
12226                                 test_amplification_isolated_external_parser);
12227 #endif
12228 
12229   return s;
12230 }
12231 
12232 int
main(int argc,char * argv[])12233 main(int argc, char *argv[]) {
12234   int i, nf;
12235   int verbosity = CK_NORMAL;
12236   Suite *s = make_suite();
12237   SRunner *sr = srunner_create(s);
12238 
12239   /* run the tests for internal helper functions */
12240   testhelper_is_whitespace_normalized();
12241 
12242   for (i = 1; i < argc; ++i) {
12243     char *opt = argv[i];
12244     if (strcmp(opt, "-v") == 0 || strcmp(opt, "--verbose") == 0)
12245       verbosity = CK_VERBOSE;
12246     else if (strcmp(opt, "-q") == 0 || strcmp(opt, "--quiet") == 0)
12247       verbosity = CK_SILENT;
12248     else {
12249       fprintf(stderr, "runtests: unknown option '%s'\n", opt);
12250       return 2;
12251     }
12252   }
12253   if (verbosity != CK_SILENT)
12254     printf("Expat version: %" XML_FMT_STR "\n", XML_ExpatVersion());
12255   srunner_run_all(sr, verbosity);
12256   nf = srunner_ntests_failed(sr);
12257   srunner_free(sr);
12258 
12259   return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
12260 }
12261