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