• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Run the Expat test suite
2                             __  __            _
3                          ___\ \/ /_ __   __ _| |_
4                         / _ \\  /| '_ \ / _` | __|
5                        |  __//  \| |_) | (_| | |_
6                         \___/_/\_\ .__/ \__,_|\__|
7                                  |_| XML parser
8 
9    Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
10    Copyright (c) 2000-2017 Expat development team
11    Licensed under the MIT license:
12 
13    Permission is  hereby granted,  free of charge,  to any  person obtaining
14    a  copy  of  this  software   and  associated  documentation  files  (the
15    "Software"),  to  deal in  the  Software  without restriction,  including
16    without  limitation the  rights  to use,  copy,  modify, merge,  publish,
17    distribute, sublicense, and/or sell copies of the Software, and to permit
18    persons  to whom  the Software  is  furnished to  do so,  subject to  the
19    following conditions:
20 
21    The above copyright  notice and this permission notice  shall be included
22    in all copies or substantial portions of the Software.
23 
24    THE  SOFTWARE  IS  PROVIDED  "AS  IS",  WITHOUT  WARRANTY  OF  ANY  KIND,
25    EXPRESS  OR IMPLIED,  INCLUDING  BUT  NOT LIMITED  TO  THE WARRANTIES  OF
26    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
27    NO EVENT SHALL THE AUTHORS OR  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
28    DAMAGES OR  OTHER LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT,  TORT OR
29    OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
30    USE OR OTHER DEALINGS IN THE SOFTWARE.
31 */
32 
33 #if defined(NDEBUG)
34 # undef NDEBUG  /* because test suite relies on assert(...) at the moment */
35 #endif
36 
37 #ifdef HAVE_EXPAT_CONFIG_H
38 # include <expat_config.h>
39 #endif
40 
41 #include <assert.h>
42 #include <stdlib.h>
43 #include <stdio.h>
44 #include <string.h>
45 #include <stdint.h>
46 #include <stddef.h>  /* ptrdiff_t */
47 #include <ctype.h>
48 #include <limits.h>
49 
50 #if ! defined(__cplusplus)
51 # if defined(_MSC_VER) && (_MSC_VER <= 1700)
52    /* for vs2012/11.0/1700 and earlier Visual Studio compilers */
53 #  define bool   int
54 #  define false  0
55 #  define true   1
56 # else
57 #  include <stdbool.h>
58 # endif
59 #endif
60 
61 
62 #include "expat.h"
63 #include "chardata.h"
64 #include "structdata.h"
65 #include "internal.h"  /* for UNUSED_P only */
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 
100 static XML_Parser parser = NULL;
101 
102 
103 static void
basic_setup(void)104 basic_setup(void)
105 {
106     parser = XML_ParserCreate(NULL);
107     if (parser == NULL)
108         fail("Parser not created.");
109 }
110 
111 static void
basic_teardown(void)112 basic_teardown(void)
113 {
114     if (parser != NULL) {
115         XML_ParserFree(parser);
116         parser = NULL;
117     }
118 }
119 
120 /* Generate a failure using the parser state to create an error message;
121    this should be used when the parser reports an error we weren't
122    expecting.
123 */
124 static void
_xml_failure(XML_Parser parser,const char * file,int line)125 _xml_failure(XML_Parser parser, const char *file, int line)
126 {
127     char buffer[1024];
128     enum XML_Error err = XML_GetErrorCode(parser);
129     sprintf(buffer,
130             "    %d: %" XML_FMT_STR " (line %"
131                 XML_FMT_INT_MOD "u, offset %"
132                 XML_FMT_INT_MOD "u)\n    reported from %s, line %d\n",
133             err,
134             XML_ErrorString(err),
135             XML_GetCurrentLineNumber(parser),
136             XML_GetCurrentColumnNumber(parser),
137             file, line);
138     _fail_unless(0, file, line, buffer);
139 }
140 
141 static enum XML_Status
_XML_Parse_SINGLE_BYTES(XML_Parser parser,const char * s,int len,int isFinal)142 _XML_Parse_SINGLE_BYTES(XML_Parser parser, const char *s, int len, int isFinal)
143 {
144     enum XML_Status res = XML_STATUS_ERROR;
145     int offset = 0;
146 
147     if (len == 0) {
148         return XML_Parse(parser, s, len, isFinal);
149     }
150 
151     for (; offset < len; offset++) {
152         const int innerIsFinal = (offset == len - 1) && isFinal;
153         const char c = s[offset]; /* to help out-of-bounds detection */
154         res = XML_Parse(parser, &c, sizeof(char), innerIsFinal);
155         if (res != XML_STATUS_OK) {
156             return res;
157         }
158     }
159     return res;
160 }
161 
162 #define xml_failure(parser) _xml_failure((parser), __FILE__, __LINE__)
163 
164 static void
_expect_failure(const char * text,enum XML_Error errorCode,const char * errorMessage,const char * file,int lineno)165 _expect_failure(const char *text, enum XML_Error errorCode, const char *errorMessage,
166                 const char *file, int lineno)
167 {
168     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) == XML_STATUS_OK)
169         /* Hackish use of _fail_unless() macro, but let's us report
170            the right filename and line number. */
171         _fail_unless(0, file, lineno, errorMessage);
172     if (XML_GetErrorCode(parser) != errorCode)
173         _xml_failure(parser, file, lineno);
174 }
175 
176 #define expect_failure(text, errorCode, errorMessage) \
177         _expect_failure((text), (errorCode), (errorMessage), \
178                         __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 
205 static void XMLCALL
dummy_xdecl_handler(void * UNUSED_P (userData),const XML_Char * UNUSED_P (version),const XML_Char * UNUSED_P (encoding),int UNUSED_P (standalone))206 dummy_xdecl_handler(void *UNUSED_P(userData),
207                     const XML_Char *UNUSED_P(version),
208                     const XML_Char *UNUSED_P(encoding),
209                     int UNUSED_P(standalone))
210 {}
211 
212 static void XMLCALL
dummy_start_doctype_handler(void * UNUSED_P (userData),const XML_Char * UNUSED_P (doctypeName),const XML_Char * UNUSED_P (sysid),const XML_Char * UNUSED_P (pubid),int UNUSED_P (has_internal_subset))213 dummy_start_doctype_handler(void           *UNUSED_P(userData),
214                             const XML_Char *UNUSED_P(doctypeName),
215                             const XML_Char *UNUSED_P(sysid),
216                             const XML_Char *UNUSED_P(pubid),
217                             int            UNUSED_P(has_internal_subset))
218 {
219     dummy_handler_flags |= DUMMY_START_DOCTYPE_HANDLER_FLAG;
220 }
221 
222 static void XMLCALL
dummy_end_doctype_handler(void * UNUSED_P (userData))223 dummy_end_doctype_handler(void *UNUSED_P(userData))
224 {
225     dummy_handler_flags |= DUMMY_END_DOCTYPE_HANDLER_FLAG;
226 }
227 
228 static void XMLCALL
dummy_entity_decl_handler(void * UNUSED_P (userData),const XML_Char * UNUSED_P (entityName),int UNUSED_P (is_parameter_entity),const XML_Char * UNUSED_P (value),int UNUSED_P (value_length),const XML_Char * UNUSED_P (base),const XML_Char * UNUSED_P (systemId),const XML_Char * UNUSED_P (publicId),const XML_Char * UNUSED_P (notationName))229 dummy_entity_decl_handler(void           *UNUSED_P(userData),
230                           const XML_Char *UNUSED_P(entityName),
231                           int            UNUSED_P(is_parameter_entity),
232                           const XML_Char *UNUSED_P(value),
233                           int            UNUSED_P(value_length),
234                           const XML_Char *UNUSED_P(base),
235                           const XML_Char *UNUSED_P(systemId),
236                           const XML_Char *UNUSED_P(publicId),
237                           const XML_Char *UNUSED_P(notationName))
238 {
239     dummy_handler_flags |= DUMMY_ENTITY_DECL_HANDLER_FLAG;
240 }
241 
242 static void XMLCALL
dummy_notation_decl_handler(void * UNUSED_P (userData),const XML_Char * UNUSED_P (notationName),const XML_Char * UNUSED_P (base),const XML_Char * UNUSED_P (systemId),const XML_Char * UNUSED_P (publicId))243 dummy_notation_decl_handler(void *UNUSED_P(userData),
244                             const XML_Char *UNUSED_P(notationName),
245                             const XML_Char *UNUSED_P(base),
246                             const XML_Char *UNUSED_P(systemId),
247                             const XML_Char *UNUSED_P(publicId))
248 {
249     dummy_handler_flags |= DUMMY_NOTATION_DECL_HANDLER_FLAG;
250 }
251 
252 static void XMLCALL
dummy_element_decl_handler(void * UNUSED_P (userData),const XML_Char * UNUSED_P (name),XML_Content * model)253 dummy_element_decl_handler(void *UNUSED_P(userData),
254                            const XML_Char *UNUSED_P(name),
255                            XML_Content *model)
256 {
257     /* The content model must be freed by the handler.  Unfortunately
258      * we cannot pass the parser as the userData because this is used
259      * with other handlers that require other userData.
260      */
261     XML_FreeContentModel(parser, model);
262     dummy_handler_flags |= DUMMY_ELEMENT_DECL_HANDLER_FLAG;
263 }
264 
265 static void XMLCALL
dummy_attlist_decl_handler(void * UNUSED_P (userData),const XML_Char * UNUSED_P (elname),const XML_Char * UNUSED_P (attname),const XML_Char * UNUSED_P (att_type),const XML_Char * UNUSED_P (dflt),int UNUSED_P (isrequired))266 dummy_attlist_decl_handler(void           *UNUSED_P(userData),
267                            const XML_Char *UNUSED_P(elname),
268                            const XML_Char *UNUSED_P(attname),
269                            const XML_Char *UNUSED_P(att_type),
270                            const XML_Char *UNUSED_P(dflt),
271                            int            UNUSED_P(isrequired))
272 {
273     dummy_handler_flags |= DUMMY_ATTLIST_DECL_HANDLER_FLAG;
274 }
275 
276 static void XMLCALL
dummy_comment_handler(void * UNUSED_P (userData),const XML_Char * UNUSED_P (data))277 dummy_comment_handler(void *UNUSED_P(userData), const XML_Char *UNUSED_P(data))
278 {
279     dummy_handler_flags |= DUMMY_COMMENT_HANDLER_FLAG;
280 }
281 
282 static void XMLCALL
dummy_pi_handler(void * UNUSED_P (userData),const XML_Char * UNUSED_P (target),const XML_Char * UNUSED_P (data))283 dummy_pi_handler(void *UNUSED_P(userData), const XML_Char *UNUSED_P(target), const XML_Char *UNUSED_P(data))
284 {
285     dummy_handler_flags |= DUMMY_PI_HANDLER_FLAG;
286 }
287 
288 static void XMLCALL
dummy_start_element(void * UNUSED_P (userData),const XML_Char * UNUSED_P (name),const XML_Char ** UNUSED_P (atts))289 dummy_start_element(void *UNUSED_P(userData),
290                     const XML_Char *UNUSED_P(name), const XML_Char **UNUSED_P(atts))
291 {
292     dummy_handler_flags |= DUMMY_START_ELEMENT_HANDLER_FLAG;
293 }
294 
295 static void XMLCALL
dummy_end_element(void * UNUSED_P (userData),const XML_Char * UNUSED_P (name))296 dummy_end_element(void *UNUSED_P(userData), const XML_Char *UNUSED_P(name))
297 {}
298 
299 static void XMLCALL
dummy_start_cdata_handler(void * UNUSED_P (userData))300 dummy_start_cdata_handler(void *UNUSED_P(userData))
301 {
302     dummy_handler_flags |= DUMMY_START_CDATA_HANDLER_FLAG;
303 }
304 
305 static void XMLCALL
dummy_end_cdata_handler(void * UNUSED_P (userData))306 dummy_end_cdata_handler(void *UNUSED_P(userData))
307 {
308     dummy_handler_flags |= DUMMY_END_CDATA_HANDLER_FLAG;
309 }
310 
311 static void XMLCALL
dummy_cdata_handler(void * UNUSED_P (userData),const XML_Char * UNUSED_P (s),int UNUSED_P (len))312 dummy_cdata_handler(void *UNUSED_P(userData),
313                     const XML_Char *UNUSED_P(s),
314                     int UNUSED_P(len))
315 {}
316 
317 static void XMLCALL
dummy_start_namespace_decl_handler(void * UNUSED_P (userData),const XML_Char * UNUSED_P (prefix),const XML_Char * UNUSED_P (uri))318 dummy_start_namespace_decl_handler(void *UNUSED_P(userData),
319                                    const XML_Char *UNUSED_P(prefix),
320                                    const XML_Char *UNUSED_P(uri))
321 {
322     dummy_handler_flags |= DUMMY_START_NS_DECL_HANDLER_FLAG;
323 }
324 
325 static void XMLCALL
dummy_end_namespace_decl_handler(void * UNUSED_P (userData),const XML_Char * UNUSED_P (prefix))326 dummy_end_namespace_decl_handler(void *UNUSED_P(userData),
327                                  const XML_Char *UNUSED_P(prefix))
328 {
329     dummy_handler_flags |= DUMMY_END_NS_DECL_HANDLER_FLAG;
330 }
331 
332 /* This handler is obsolete, but while the code exists we should
333  * ensure that dealing with the handler is covered by tests.
334  */
335 static void XMLCALL
dummy_unparsed_entity_decl_handler(void * UNUSED_P (userData),const XML_Char * UNUSED_P (entityName),const XML_Char * UNUSED_P (base),const XML_Char * UNUSED_P (systemId),const XML_Char * UNUSED_P (publicId),const XML_Char * UNUSED_P (notationName))336 dummy_unparsed_entity_decl_handler(void *UNUSED_P(userData),
337                                    const XML_Char *UNUSED_P(entityName),
338                                    const XML_Char *UNUSED_P(base),
339                                    const XML_Char *UNUSED_P(systemId),
340                                    const XML_Char *UNUSED_P(publicId),
341                                    const XML_Char *UNUSED_P(notationName))
342 {
343     dummy_handler_flags |= DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG;
344 }
345 
346 static void XMLCALL
dummy_default_handler(void * UNUSED_P (userData),const XML_Char * UNUSED_P (s),int UNUSED_P (len))347 dummy_default_handler(void *UNUSED_P(userData),
348                       const XML_Char *UNUSED_P(s),
349                       int UNUSED_P(len))
350 {}
351 
352 static void XMLCALL
dummy_start_doctype_decl_handler(void * UNUSED_P (userData),const XML_Char * UNUSED_P (doctypeName),const XML_Char * UNUSED_P (sysid),const XML_Char * UNUSED_P (pubid),int UNUSED_P (has_internal_subset))353 dummy_start_doctype_decl_handler(void *UNUSED_P(userData),
354                                  const XML_Char *UNUSED_P(doctypeName),
355                                  const XML_Char *UNUSED_P(sysid),
356                                  const XML_Char *UNUSED_P(pubid),
357                                  int UNUSED_P(has_internal_subset))
358 {
359     dummy_handler_flags |= DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG;
360 }
361 
362 static void XMLCALL
dummy_end_doctype_decl_handler(void * UNUSED_P (userData))363 dummy_end_doctype_decl_handler(void *UNUSED_P(userData))
364 {
365     dummy_handler_flags |= DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG;
366 }
367 
368 static void XMLCALL
dummy_skip_handler(void * UNUSED_P (userData),const XML_Char * UNUSED_P (entityName),int UNUSED_P (is_parameter_entity))369 dummy_skip_handler(void *UNUSED_P(userData),
370                    const XML_Char *UNUSED_P(entityName),
371                    int UNUSED_P(is_parameter_entity))
372 {
373     dummy_handler_flags |= DUMMY_SKIP_HANDLER_FLAG;
374 }
375 
376 /* Useful external entity handler */
377 typedef struct ExtOption {
378     const XML_Char *system_id;
379     const char *parse_text;
380 } ExtOption;
381 
382 static int XMLCALL
external_entity_optioner(XML_Parser parser,const XML_Char * context,const XML_Char * UNUSED_P (base),const XML_Char * systemId,const XML_Char * UNUSED_P (publicId))383 external_entity_optioner(XML_Parser parser,
384                          const XML_Char *context,
385                          const XML_Char *UNUSED_P(base),
386                          const XML_Char *systemId,
387                          const XML_Char *UNUSED_P(publicId))
388 {
389     ExtOption *options = (ExtOption *)XML_GetUserData(parser);
390     XML_Parser ext_parser;
391 
392     while (options->parse_text != NULL) {
393         if (!xcstrcmp(systemId, options->system_id)) {
394             enum XML_Status rc;
395             ext_parser =
396                 XML_ExternalEntityParserCreate(parser, context, NULL);
397             if (ext_parser == NULL)
398                 return XML_STATUS_ERROR;
399             rc = _XML_Parse_SINGLE_BYTES(ext_parser, options->parse_text,
400                                          strlen(options->parse_text),
401                                          XML_TRUE);
402             XML_ParserFree(ext_parser);
403             return rc;
404         }
405         options++;
406     }
407     fail("No suitable option found");
408     return XML_STATUS_ERROR;
409 }
410 
411 /*
412  * Parameter entity evaluation support.
413  */
414 #define ENTITY_MATCH_FAIL      (-1)
415 #define ENTITY_MATCH_NOT_FOUND  (0)
416 #define ENTITY_MATCH_SUCCESS    (1)
417 static const XML_Char *entity_name_to_match = NULL;
418 static const XML_Char *entity_value_to_match = NULL;
419 static int entity_match_flag = ENTITY_MATCH_NOT_FOUND;
420 
421 static void XMLCALL
param_entity_match_handler(void * UNUSED_P (userData),const XML_Char * entityName,int is_parameter_entity,const XML_Char * value,int value_length,const XML_Char * UNUSED_P (base),const XML_Char * UNUSED_P (systemId),const XML_Char * UNUSED_P (publicId),const XML_Char * UNUSED_P (notationName))422 param_entity_match_handler(void           *UNUSED_P(userData),
423                            const XML_Char *entityName,
424                            int            is_parameter_entity,
425                            const XML_Char *value,
426                            int            value_length,
427                            const XML_Char *UNUSED_P(base),
428                            const XML_Char *UNUSED_P(systemId),
429                            const XML_Char *UNUSED_P(publicId),
430                            const XML_Char *UNUSED_P(notationName))
431 {
432     if (!is_parameter_entity ||
433         entity_name_to_match == NULL ||
434         entity_value_to_match == NULL) {
435         return;
436     }
437     if (!xcstrcmp(entityName, entity_name_to_match)) {
438         /* The cast here is safe because we control the horizontal and
439          * the vertical, and we therefore know our strings are never
440          * going to overflow an int.
441          */
442         if (value_length != (int)xcstrlen(entity_value_to_match) ||
443             xcstrncmp(value, entity_value_to_match, value_length)) {
444             entity_match_flag = ENTITY_MATCH_FAIL;
445         } else {
446             entity_match_flag = ENTITY_MATCH_SUCCESS;
447         }
448     }
449     /* Else leave the match flag alone */
450 }
451 
452 /*
453  * Character & encoding tests.
454  */
455 
START_TEST(test_nul_byte)456 START_TEST(test_nul_byte)
457 {
458     char text[] = "<doc>\0</doc>";
459 
460     /* test that a NUL byte (in US-ASCII data) is an error */
461     if (_XML_Parse_SINGLE_BYTES(parser, text, sizeof(text) - 1, XML_TRUE) == XML_STATUS_OK)
462         fail("Parser did not report error on NUL-byte.");
463     if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN)
464         xml_failure(parser);
465 }
466 END_TEST
467 
468 
START_TEST(test_u0000_char)469 START_TEST(test_u0000_char)
470 {
471     /* test that a NUL byte (in US-ASCII data) is an error */
472     expect_failure("<doc>&#0;</doc>",
473                    XML_ERROR_BAD_CHAR_REF,
474                    "Parser did not report error on NUL-byte.");
475 }
476 END_TEST
477 
START_TEST(test_siphash_self)478 START_TEST(test_siphash_self)
479 {
480     if (! sip24_valid())
481         fail("SipHash self-test failed");
482 }
483 END_TEST
484 
START_TEST(test_siphash_spec)485 START_TEST(test_siphash_spec)
486 {
487     /* https://131002.net/siphash/siphash.pdf (page 19, "Test values") */
488     const char message[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09"
489             "\x0a\x0b\x0c\x0d\x0e";
490     const size_t len = sizeof(message) - 1;
491     const uint64_t expected = _SIP_ULL(0xa129ca61U, 0x49be45e5U);
492     struct siphash state;
493     struct sipkey key;
494     (void)sip_tobin;
495 
496     sip_tokey(&key,
497             "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09"
498             "\x0a\x0b\x0c\x0d\x0e\x0f");
499     sip24_init(&state, &key);
500 
501     /* Cover spread across calls */
502     sip24_update(&state, message, 4);
503     sip24_update(&state, message + 4, len - 4);
504 
505     /* Cover null length */
506     sip24_update(&state, message, 0);
507 
508     if (sip24_final(&state) != expected)
509         fail("sip24_final failed spec test\n");
510 
511     /* Cover wrapper */
512     if (siphash24(message, len, &key) != expected)
513         fail("siphash24 failed spec test\n");
514 }
515 END_TEST
516 
START_TEST(test_bom_utf8)517 START_TEST(test_bom_utf8)
518 {
519     /* This test is really just making sure we don't core on a UTF-8 BOM. */
520     const char *text = "\357\273\277<e/>";
521 
522     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
523         xml_failure(parser);
524 }
525 END_TEST
526 
START_TEST(test_bom_utf16_be)527 START_TEST(test_bom_utf16_be)
528 {
529     char text[] = "\376\377\0<\0e\0/\0>";
530 
531     if (_XML_Parse_SINGLE_BYTES(parser, text, sizeof(text)-1, XML_TRUE) == XML_STATUS_ERROR)
532         xml_failure(parser);
533 }
534 END_TEST
535 
START_TEST(test_bom_utf16_le)536 START_TEST(test_bom_utf16_le)
537 {
538     char text[] = "\377\376<\0e\0/\0>\0";
539 
540     if (_XML_Parse_SINGLE_BYTES(parser, text, sizeof(text)-1, XML_TRUE) == XML_STATUS_ERROR)
541         xml_failure(parser);
542 }
543 END_TEST
544 
545 /* Parse whole buffer at once to exercise a different code path */
START_TEST(test_nobom_utf16_le)546 START_TEST(test_nobom_utf16_le)
547 {
548     char text[] = " \0<\0e\0/\0>\0";
549 
550     if (XML_Parse(parser, text, sizeof(text)-1, XML_TRUE) == XML_STATUS_ERROR)
551         xml_failure(parser);
552 }
553 END_TEST
554 
555 static void XMLCALL
accumulate_characters(void * userData,const XML_Char * s,int len)556 accumulate_characters(void *userData, const XML_Char *s, int len)
557 {
558     CharData_AppendXMLChars((CharData *)userData, s, len);
559 }
560 
561 static void XMLCALL
accumulate_attribute(void * userData,const XML_Char * UNUSED_P (name),const XML_Char ** atts)562 accumulate_attribute(void *userData, const XML_Char *UNUSED_P(name),
563                      const XML_Char **atts)
564 {
565     CharData *storage = (CharData *)userData;
566 
567     /* Check there are attributes to deal with */
568     if (atts == NULL)
569         return;
570 
571     while (storage->count < 0 && atts[0] != NULL) {
572         /* "accumulate" the value of the first attribute we see */
573         CharData_AppendXMLChars(storage, atts[1], -1);
574         atts += 2;
575     }
576 }
577 
578 
579 static void
_run_character_check(const char * text,const XML_Char * expected,const char * file,int line)580 _run_character_check(const char *text, const XML_Char *expected,
581                      const char *file, int line)
582 {
583     CharData storage;
584 
585     CharData_Init(&storage);
586     XML_SetUserData(parser, &storage);
587     XML_SetCharacterDataHandler(parser, accumulate_characters);
588     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
589         _xml_failure(parser, file, line);
590     CharData_CheckXMLChars(&storage, expected);
591 }
592 
593 #define run_character_check(text, expected) \
594         _run_character_check(text, expected, __FILE__, __LINE__)
595 
596 static void
_run_attribute_check(const char * text,const XML_Char * expected,const char * file,int line)597 _run_attribute_check(const char *text, const XML_Char *expected,
598                      const char *file, int line)
599 {
600     CharData storage;
601 
602     CharData_Init(&storage);
603     XML_SetUserData(parser, &storage);
604     XML_SetStartElementHandler(parser, accumulate_attribute);
605     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
606         _xml_failure(parser, file, line);
607     CharData_CheckXMLChars(&storage, expected);
608 }
609 
610 #define run_attribute_check(text, expected) \
611         _run_attribute_check(text, expected, __FILE__, __LINE__)
612 
613 typedef struct ExtTest {
614     const char *parse_text;
615     const XML_Char *encoding;
616     CharData *storage;
617 } ExtTest;
618 
619 static void XMLCALL
ext_accumulate_characters(void * userData,const XML_Char * s,int len)620 ext_accumulate_characters(void *userData, const XML_Char *s, int len)
621 {
622     ExtTest *test_data = (ExtTest *)userData;
623     accumulate_characters(test_data->storage, s, len);
624 }
625 
626 static void
_run_ext_character_check(const char * text,ExtTest * test_data,const XML_Char * expected,const char * file,int line)627 _run_ext_character_check(const char *text,
628                          ExtTest *test_data,
629                          const XML_Char *expected,
630                          const char *file, int line)
631 {
632     CharData storage;
633 
634     CharData_Init(&storage);
635     test_data->storage = &storage;
636     XML_SetUserData(parser, test_data);
637     XML_SetCharacterDataHandler(parser, ext_accumulate_characters);
638     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
639                                 XML_TRUE) == XML_STATUS_ERROR)
640         _xml_failure(parser, file, line);
641     CharData_CheckXMLChars(&storage, expected);
642 }
643 
644 #define run_ext_character_check(text, test_data, expected)               \
645     _run_ext_character_check(text, test_data, expected, __FILE__, __LINE__)
646 
647 /* Regression test for SF bug #491986. */
START_TEST(test_danish_latin1)648 START_TEST(test_danish_latin1)
649 {
650     const char *text =
651         "<?xml version='1.0' encoding='iso-8859-1'?>\n"
652         "<e>J\xF8rgen \xE6\xF8\xE5\xC6\xD8\xC5</e>";
653 #ifdef XML_UNICODE
654     const XML_Char *expected =
655         XCS("J\x00f8rgen \x00e6\x00f8\x00e5\x00c6\x00d8\x00c5");
656 #else
657     const XML_Char *expected =
658         XCS("J\xC3\xB8rgen \xC3\xA6\xC3\xB8\xC3\xA5\xC3\x86\xC3\x98\xC3\x85");
659 #endif
660     run_character_check(text, expected);
661 }
662 END_TEST
663 
664 
665 /* Regression test for SF bug #514281. */
START_TEST(test_french_charref_hexidecimal)666 START_TEST(test_french_charref_hexidecimal)
667 {
668     const char *text =
669         "<?xml version='1.0' encoding='iso-8859-1'?>\n"
670         "<doc>&#xE9;&#xE8;&#xE0;&#xE7;&#xEA;&#xC8;</doc>";
671 #ifdef XML_UNICODE
672     const XML_Char *expected =
673         XCS("\x00e9\x00e8\x00e0\x00e7\x00ea\x00c8");
674 #else
675     const XML_Char *expected =
676         XCS("\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88");
677 #endif
678     run_character_check(text, expected);
679 }
680 END_TEST
681 
START_TEST(test_french_charref_decimal)682 START_TEST(test_french_charref_decimal)
683 {
684     const char *text =
685         "<?xml version='1.0' encoding='iso-8859-1'?>\n"
686         "<doc>&#233;&#232;&#224;&#231;&#234;&#200;</doc>";
687 #ifdef XML_UNICODE
688     const XML_Char *expected =
689         XCS("\x00e9\x00e8\x00e0\x00e7\x00ea\x00c8");
690 #else
691     const XML_Char *expected =
692         XCS("\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88");
693 #endif
694     run_character_check(text, expected);
695 }
696 END_TEST
697 
START_TEST(test_french_latin1)698 START_TEST(test_french_latin1)
699 {
700     const char *text =
701         "<?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 =
705         XCS("\x00e9\x00e8\x00e0\x00e7\x00ea\x00c8");
706 #else
707     const XML_Char *expected =
708         XCS("\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88");
709 #endif
710     run_character_check(text, expected);
711 }
712 END_TEST
713 
START_TEST(test_french_utf8)714 START_TEST(test_french_utf8)
715 {
716     const char *text =
717         "<?xml version='1.0' encoding='utf-8'?>\n"
718         "<doc>\xC3\xA9</doc>";
719 #ifdef XML_UNICODE
720     const XML_Char *expected = XCS("\x00e9");
721 #else
722     const XML_Char *expected = XCS("\xC3\xA9");
723 #endif
724     run_character_check(text, expected);
725 }
726 END_TEST
727 
728 /* Regression test for SF bug #600479.
729    XXX There should be a test that exercises all legal XML Unicode
730    characters as PCDATA and attribute value content, and XML Name
731    characters as part of element and attribute names.
732 */
START_TEST(test_utf8_false_rejection)733 START_TEST(test_utf8_false_rejection)
734 {
735     const char *text = "<doc>\xEF\xBA\xBF</doc>";
736 #ifdef XML_UNICODE
737     const XML_Char *expected = XCS("\xfebf");
738 #else
739     const XML_Char *expected = XCS("\xEF\xBA\xBF");
740 #endif
741     run_character_check(text, expected);
742 }
743 END_TEST
744 
745 /* Regression test for SF bug #477667.
746    This test assures that any 8-bit character followed by a 7-bit
747    character will not be mistakenly interpreted as a valid UTF-8
748    sequence.
749 */
START_TEST(test_illegal_utf8)750 START_TEST(test_illegal_utf8)
751 {
752     char text[100];
753     int i;
754 
755     for (i = 128; i <= 255; ++i) {
756         sprintf(text, "<e>%ccd</e>", i);
757         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) == XML_STATUS_OK) {
758             sprintf(text,
759                     "expected token error for '%c' (ordinal %d) in UTF-8 text",
760                     i, i);
761             fail(text);
762         }
763         else if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN)
764             xml_failure(parser);
765         /* Reset the parser since we use the same parser repeatedly. */
766         XML_ParserReset(parser, NULL);
767     }
768 }
769 END_TEST
770 
771 
772 /* Examples, not masks: */
773 #define UTF8_LEAD_1  "\x7f"  /* 0b01111111 */
774 #define UTF8_LEAD_2  "\xdf"  /* 0b11011111 */
775 #define UTF8_LEAD_3  "\xef"  /* 0b11101111 */
776 #define UTF8_LEAD_4  "\xf7"  /* 0b11110111 */
777 #define UTF8_FOLLOW  "\xbf"  /* 0b10111111 */
778 
START_TEST(test_utf8_auto_align)779 START_TEST(test_utf8_auto_align)
780 {
781     struct TestCase {
782         ptrdiff_t expectedMovementInChars;
783         const char * input;
784     };
785 
786     struct TestCase cases[] = {
787         {00, ""},
788 
789         {00, UTF8_LEAD_1},
790 
791         {-1, UTF8_LEAD_2},
792         {00, UTF8_LEAD_2 UTF8_FOLLOW},
793 
794         {-1, UTF8_LEAD_3},
795         {-2, UTF8_LEAD_3 UTF8_FOLLOW},
796         {00, UTF8_LEAD_3 UTF8_FOLLOW UTF8_FOLLOW},
797 
798         {-1, UTF8_LEAD_4},
799         {-2, UTF8_LEAD_4 UTF8_FOLLOW},
800         {-3, UTF8_LEAD_4 UTF8_FOLLOW UTF8_FOLLOW},
801         {00, UTF8_LEAD_4 UTF8_FOLLOW UTF8_FOLLOW UTF8_FOLLOW},
802     };
803 
804     size_t i = 0;
805     bool success = true;
806     for (; i < sizeof(cases) / sizeof(*cases); i++) {
807         const char * fromLim = cases[i].input + strlen(cases[i].input);
808         const char * const fromLimInitially = fromLim;
809         ptrdiff_t actualMovementInChars;
810 
811         _INTERNAL_trim_to_complete_utf8_characters(cases[i].input, &fromLim);
812 
813         actualMovementInChars = (fromLim - fromLimInitially);
814         if (actualMovementInChars != cases[i].expectedMovementInChars) {
815             size_t j = 0;
816             success = false;
817             printf("[-] UTF-8 case %2u: Expected movement by %2d chars"
818                     ", actually moved by %2d chars: \"",
819                     (unsigned)(i + 1),
820                     (int)cases[i].expectedMovementInChars,
821                     (int)actualMovementInChars);
822             for (; j < strlen(cases[i].input); j++) {
823                 printf("\\x%02x", (unsigned char)cases[i].input[j]);
824             }
825             printf("\"\n");
826         }
827     }
828 
829     if (! success) {
830         fail("UTF-8 auto-alignment is not bullet-proof\n");
831     }
832 }
833 END_TEST
834 
START_TEST(test_utf16)835 START_TEST(test_utf16)
836 {
837     /* <?xml version="1.0" encoding="UTF-16"?>
838      *  <doc a='123'>some {A} text</doc>
839      *
840      * where {A} is U+FF21, FULLWIDTH LATIN CAPITAL LETTER A
841      */
842     char text[] =
843         "\000<\000?\000x\000m\000\154\000 \000v\000e\000r\000s\000i\000o"
844         "\000n\000=\000'\0001\000.\000\060\000'\000 \000e\000n\000c\000o"
845         "\000d\000i\000n\000g\000=\000'\000U\000T\000F\000-\0001\000\066"
846         "\000'\000?\000>\000\n"
847         "\000<\000d\000o\000c\000 \000a\000=\000'\0001\0002\0003\000'\000>"
848         "\000s\000o\000m\000e\000 \xff\x21\000 \000t\000e\000x\000t\000"
849         "<\000/\000d\000o\000c\000>";
850 #ifdef XML_UNICODE
851     const XML_Char *expected = XCS("some \xff21 text");
852 #else
853     const XML_Char *expected = XCS("some \357\274\241 text");
854 #endif
855     CharData storage;
856 
857     CharData_Init(&storage);
858     XML_SetUserData(parser, &storage);
859     XML_SetCharacterDataHandler(parser, accumulate_characters);
860     if (_XML_Parse_SINGLE_BYTES(parser, text, sizeof(text)-1, XML_TRUE) == XML_STATUS_ERROR)
861         xml_failure(parser);
862     CharData_CheckXMLChars(&storage, expected);
863 }
864 END_TEST
865 
START_TEST(test_utf16_le_epilog_newline)866 START_TEST(test_utf16_le_epilog_newline)
867 {
868     unsigned int first_chunk_bytes = 17;
869     char text[] =
870         "\xFF\xFE"                      /* BOM */
871         "<\000e\000/\000>\000"          /* document element */
872         "\r\000\n\000\r\000\n\000";     /* epilog */
873 
874     if (first_chunk_bytes >= sizeof(text) - 1)
875         fail("bad value of first_chunk_bytes");
876     if (  _XML_Parse_SINGLE_BYTES(parser, text, first_chunk_bytes, XML_FALSE)
877           == XML_STATUS_ERROR)
878         xml_failure(parser);
879     else {
880         enum XML_Status rc;
881         rc = _XML_Parse_SINGLE_BYTES(parser, text + first_chunk_bytes,
882                        sizeof(text) - first_chunk_bytes - 1, XML_TRUE);
883         if (rc == XML_STATUS_ERROR)
884             xml_failure(parser);
885     }
886 }
887 END_TEST
888 
889 /* Test that an outright lie in the encoding is faulted */
START_TEST(test_not_utf16)890 START_TEST(test_not_utf16)
891 {
892     const char *text =
893         "<?xml version='1.0' encoding='utf-16'?>"
894         "<doc>Hi</doc>";
895 
896     /* Use a handler to provoke the appropriate code paths */
897     XML_SetXmlDeclHandler(parser, dummy_xdecl_handler);
898     expect_failure(text,
899                    XML_ERROR_INCORRECT_ENCODING,
900                    "UTF-16 declared in UTF-8 not faulted");
901 }
902 END_TEST
903 
904 /* Test that an unknown encoding is rejected */
START_TEST(test_bad_encoding)905 START_TEST(test_bad_encoding)
906 {
907     const char *text = "<doc>Hi</doc>";
908 
909     if (!XML_SetEncoding(parser, XCS("unknown-encoding")))
910         fail("XML_SetEncoding failed");
911     expect_failure(text,
912                    XML_ERROR_UNKNOWN_ENCODING,
913                    "Unknown encoding not faulted");
914 }
915 END_TEST
916 
917 /* Regression test for SF bug #481609, #774028. */
START_TEST(test_latin1_umlauts)918 START_TEST(test_latin1_umlauts)
919 {
920     const char *text =
921         "<?xml version='1.0' encoding='iso-8859-1'?>\n"
922         "<e a='\xE4 \xF6 \xFC &#228; &#246; &#252; &#x00E4; &#x0F6; &#xFC; >'\n"
923         "  >\xE4 \xF6 \xFC &#228; &#246; &#252; &#x00E4; &#x0F6; &#xFC; ></e>";
924 #ifdef XML_UNICODE
925     /* Expected results in UTF-16 */
926     const XML_Char *expected =
927         XCS("\x00e4 \x00f6 \x00fc ")
928         XCS("\x00e4 \x00f6 \x00fc ")
929         XCS("\x00e4 \x00f6 \x00fc >");
930 #else
931     /* Expected results in UTF-8 */
932     const XML_Char *expected =
933         XCS("\xC3\xA4 \xC3\xB6 \xC3\xBC ")
934         XCS("\xC3\xA4 \xC3\xB6 \xC3\xBC ")
935         XCS("\xC3\xA4 \xC3\xB6 \xC3\xBC >");
936 #endif
937 
938     run_character_check(text, expected);
939     XML_ParserReset(parser, NULL);
940     run_attribute_check(text, expected);
941     /* Repeat with a default handler */
942     XML_ParserReset(parser, NULL);
943     XML_SetDefaultHandler(parser, dummy_default_handler);
944     run_character_check(text, expected);
945     XML_ParserReset(parser, NULL);
946     XML_SetDefaultHandler(parser, dummy_default_handler);
947     run_attribute_check(text, expected);
948 }
949 END_TEST
950 
951 /* Test that an element name with a 4-byte UTF-8 character is rejected */
START_TEST(test_long_utf8_character)952 START_TEST(test_long_utf8_character)
953 {
954     const char *text =
955         "<?xml version='1.0' encoding='utf-8'?>\n"
956         /* 0xf0 0x90 0x80 0x80 = U+10000, the first Linear B character */
957         "<do\xf0\x90\x80\x80/>";
958     expect_failure(text,
959                    XML_ERROR_INVALID_TOKEN,
960                    "4-byte UTF-8 character in element name not faulted");
961 }
962 END_TEST
963 
964 /* Test that a long latin-1 attribute (too long to convert in one go)
965  * is correctly converted
966  */
START_TEST(test_long_latin1_attribute)967 START_TEST(test_long_latin1_attribute)
968 {
969     const char *text =
970         "<?xml version='1.0' encoding='iso-8859-1'?>\n"
971         "<doc att='"
972         /* 64 characters per line */
973         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
974         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
975         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
976         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
977         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
978         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
979         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
980         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
981         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
982         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
983         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
984         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
985         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
986         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
987         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
988         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
989         /* Last character splits across a buffer boundary */
990         "\xe4'>\n</doc>";
991 #ifdef XML_UNICODE
992     const XML_Char *expected =
993         /* 64 characters per line */
994         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
995         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
996         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
997         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
998         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
999         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1000         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1001         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1002         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1003         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1004         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1005         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1006         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1007         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1008         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1009         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO")
1010         XCS("\x00e4");
1011 #else
1012     const XML_Char *expected =
1013         /* 64 characters per line */
1014         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1015         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1016         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1017         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1018         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1019         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1020         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1021         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1022         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1023         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1024         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1025         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1026         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1027         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1028         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1029         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO")
1030         XCS("\xc3\xa4");
1031 #endif
1032 
1033     run_attribute_check(text, expected);
1034 }
1035 END_TEST
1036 
1037 
1038 /* Test that a long ASCII attribute (too long to convert in one go)
1039  * is correctly converted
1040  */
START_TEST(test_long_ascii_attribute)1041 START_TEST(test_long_ascii_attribute)
1042 {
1043     const char *text =
1044         "<?xml version='1.0' encoding='us-ascii'?>\n"
1045         "<doc att='"
1046         /* 64 characters per line */
1047         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1048         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1049         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1050         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1051         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1052         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1053         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1054         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1055         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1056         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1057         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1058         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1059         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1060         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1061         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1062         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1063         "01234'>\n</doc>";
1064     const XML_Char *expected =
1065         /* 64 characters per line */
1066         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1067         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1068         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1069         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1070         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1071         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1072         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1073         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1074         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1075         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1076         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1077         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1078         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1079         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1080         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1081         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1082         XCS("01234");
1083 
1084     run_attribute_check(text, expected);
1085 }
1086 END_TEST
1087 
1088 /* Regression test #1 for SF bug #653180. */
START_TEST(test_line_number_after_parse)1089 START_TEST(test_line_number_after_parse)
1090 {
1091     const char *text =
1092         "<tag>\n"
1093         "\n"
1094         "\n</tag>";
1095     XML_Size lineno;
1096 
1097     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_FALSE) == XML_STATUS_ERROR)
1098         xml_failure(parser);
1099     lineno = XML_GetCurrentLineNumber(parser);
1100     if (lineno != 4) {
1101         char buffer[100];
1102         sprintf(buffer,
1103             "expected 4 lines, saw %" XML_FMT_INT_MOD "u", lineno);
1104         fail(buffer);
1105     }
1106 }
1107 END_TEST
1108 
1109 /* Regression test #2 for SF bug #653180. */
START_TEST(test_column_number_after_parse)1110 START_TEST(test_column_number_after_parse)
1111 {
1112     const char *text = "<tag></tag>";
1113     XML_Size colno;
1114 
1115     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_FALSE) == XML_STATUS_ERROR)
1116         xml_failure(parser);
1117     colno = XML_GetCurrentColumnNumber(parser);
1118     if (colno != 11) {
1119         char buffer[100];
1120         sprintf(buffer,
1121             "expected 11 columns, saw %" XML_FMT_INT_MOD "u", colno);
1122         fail(buffer);
1123     }
1124 }
1125 END_TEST
1126 
1127 #define STRUCT_START_TAG 0
1128 #define STRUCT_END_TAG 1
1129 static void XMLCALL
start_element_event_handler2(void * userData,const XML_Char * name,const XML_Char ** UNUSED_P (attr))1130 start_element_event_handler2(void *userData, const XML_Char *name,
1131 			     const XML_Char **UNUSED_P(attr))
1132 {
1133     StructData *storage = (StructData *) userData;
1134     StructData_AddItem(storage, name,
1135                        XML_GetCurrentColumnNumber(parser),
1136                        XML_GetCurrentLineNumber(parser),
1137                        STRUCT_START_TAG);
1138 }
1139 
1140 static void XMLCALL
end_element_event_handler2(void * userData,const XML_Char * name)1141 end_element_event_handler2(void *userData, const XML_Char *name)
1142 {
1143     StructData *storage = (StructData *) userData;
1144     StructData_AddItem(storage, name,
1145                        XML_GetCurrentColumnNumber(parser),
1146                        XML_GetCurrentLineNumber(parser),
1147                        STRUCT_END_TAG);
1148 }
1149 
1150 /* Regression test #3 for SF bug #653180. */
START_TEST(test_line_and_column_numbers_inside_handlers)1151 START_TEST(test_line_and_column_numbers_inside_handlers)
1152 {
1153     const char *text =
1154         "<a>\n"        /* Unix end-of-line */
1155         "  <b>\r\n"    /* Windows end-of-line */
1156         "    <c/>\r"   /* Mac OS end-of-line */
1157         "  </b>\n"
1158         "  <d>\n"
1159         "    <f/>\n"
1160         "  </d>\n"
1161         "</a>";
1162     const StructDataEntry expected[] = {
1163         { XCS("a"), 0, 1, STRUCT_START_TAG },
1164         { XCS("b"), 2, 2, STRUCT_START_TAG },
1165         { XCS("c"), 4, 3, STRUCT_START_TAG },
1166         { XCS("c"), 8, 3, STRUCT_END_TAG },
1167         { XCS("b"), 2, 4, STRUCT_END_TAG },
1168         { XCS("d"), 2, 5, STRUCT_START_TAG },
1169         { XCS("f"), 4, 6, STRUCT_START_TAG },
1170         { XCS("f"), 8, 6, STRUCT_END_TAG },
1171         { XCS("d"), 2, 7, STRUCT_END_TAG },
1172         { XCS("a"), 0, 8, STRUCT_END_TAG }
1173     };
1174     const int expected_count = sizeof(expected) / sizeof(StructDataEntry);
1175     StructData storage;
1176 
1177     StructData_Init(&storage);
1178     XML_SetUserData(parser, &storage);
1179     XML_SetStartElementHandler(parser, start_element_event_handler2);
1180     XML_SetEndElementHandler(parser, end_element_event_handler2);
1181     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
1182         xml_failure(parser);
1183 
1184     StructData_CheckItems(&storage, expected, expected_count);
1185     StructData_Dispose(&storage);
1186 }
1187 END_TEST
1188 
1189 /* Regression test #4 for SF bug #653180. */
START_TEST(test_line_number_after_error)1190 START_TEST(test_line_number_after_error)
1191 {
1192     const char *text =
1193         "<a>\n"
1194         "  <b>\n"
1195         "  </a>";  /* missing </b> */
1196     XML_Size lineno;
1197     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_FALSE) != XML_STATUS_ERROR)
1198         fail("Expected a parse error");
1199 
1200     lineno = XML_GetCurrentLineNumber(parser);
1201     if (lineno != 3) {
1202         char buffer[100];
1203         sprintf(buffer, "expected 3 lines, saw %" XML_FMT_INT_MOD "u", lineno);
1204         fail(buffer);
1205     }
1206 }
1207 END_TEST
1208 
1209 /* Regression test #5 for SF bug #653180. */
START_TEST(test_column_number_after_error)1210 START_TEST(test_column_number_after_error)
1211 {
1212     const char *text =
1213         "<a>\n"
1214         "  <b>\n"
1215         "  </a>";  /* missing </b> */
1216     XML_Size colno;
1217     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_FALSE) != XML_STATUS_ERROR)
1218         fail("Expected a parse error");
1219 
1220     colno = XML_GetCurrentColumnNumber(parser);
1221     if (colno != 4) {
1222         char buffer[100];
1223         sprintf(buffer,
1224             "expected 4 columns, saw %" XML_FMT_INT_MOD "u", colno);
1225         fail(buffer);
1226     }
1227 }
1228 END_TEST
1229 
1230 /* Regression test for SF bug #478332. */
START_TEST(test_really_long_lines)1231 START_TEST(test_really_long_lines)
1232 {
1233     /* This parses an input line longer than INIT_DATA_BUF_SIZE
1234        characters long (defined to be 1024 in xmlparse.c).  We take a
1235        really cheesy approach to building the input buffer, because
1236        this avoids writing bugs in buffer-filling code.
1237     */
1238     const char *text =
1239         "<e>"
1240         /* 64 chars */
1241         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1242         /* until we have at least 1024 characters on the line: */
1243         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1244         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1245         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1246         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1247         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1248         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1249         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1250         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1251         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1252         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1253         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1254         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1255         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1256         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1257         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1258         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1259         "</e>";
1260     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
1261         xml_failure(parser);
1262 }
1263 END_TEST
1264 
1265 /* Test cdata processing across a buffer boundary */
START_TEST(test_really_long_encoded_lines)1266 START_TEST(test_really_long_encoded_lines)
1267 {
1268     /* As above, except that we want to provoke an output buffer
1269      * overflow with a non-trivial encoding.  For this we need to pass
1270      * the whole cdata in one go, not byte-by-byte.
1271      */
1272     void *buffer;
1273     const char *text =
1274         "<?xml version='1.0' encoding='iso-8859-1'?>"
1275         "<e>"
1276         /* 64 chars */
1277         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1278         /* until we have at least 1024 characters on the line: */
1279         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1280         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1281         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1282         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1283         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1284         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1285         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1286         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1287         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1288         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1289         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1290         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1291         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1292         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1293         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1294         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1295         "</e>";
1296     int parse_len = strlen(text);
1297 
1298     /* Need a cdata handler to provoke the code path we want to test */
1299     XML_SetCharacterDataHandler(parser, dummy_cdata_handler);
1300     buffer = XML_GetBuffer(parser, parse_len);
1301     if (buffer == NULL)
1302         fail("Could not allocate parse buffer");
1303     memcpy(buffer, text, parse_len);
1304     if (XML_ParseBuffer(parser, parse_len, XML_TRUE) == XML_STATUS_ERROR)
1305         xml_failure(parser);
1306 }
1307 END_TEST
1308 
1309 
1310 /*
1311  * Element event tests.
1312  */
1313 
1314 static void XMLCALL
start_element_event_handler(void * userData,const XML_Char * name,const XML_Char ** UNUSED_P (atts))1315 start_element_event_handler(void *userData,
1316                             const XML_Char *name,
1317                             const XML_Char **UNUSED_P(atts))
1318 {
1319     CharData_AppendXMLChars((CharData *)userData, name, -1);
1320 }
1321 
1322 static void XMLCALL
end_element_event_handler(void * userData,const XML_Char * name)1323 end_element_event_handler(void *userData, const XML_Char *name)
1324 {
1325     CharData *storage = (CharData *) userData;
1326     CharData_AppendXMLChars(storage, XCS("/"), 1);
1327     CharData_AppendXMLChars(storage, name, -1);
1328 }
1329 
START_TEST(test_end_element_events)1330 START_TEST(test_end_element_events)
1331 {
1332     const char *text = "<a><b><c/></b><d><f/></d></a>";
1333     const XML_Char *expected = XCS("/c/b/f/d/a");
1334     CharData storage;
1335 
1336     CharData_Init(&storage);
1337     XML_SetUserData(parser, &storage);
1338     XML_SetEndElementHandler(parser, end_element_event_handler);
1339     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
1340         xml_failure(parser);
1341     CharData_CheckXMLChars(&storage, expected);
1342 }
1343 END_TEST
1344 
1345 
1346 /*
1347  * Attribute tests.
1348  */
1349 
1350 /* Helpers used by the following test; this checks any "attr" and "refs"
1351    attributes to make sure whitespace has been normalized.
1352 
1353    Return true if whitespace has been normalized in a string, using
1354    the rules for attribute value normalization.  The 'is_cdata' flag
1355    is needed since CDATA attributes don't need to have multiple
1356    whitespace characters collapsed to a single space, while other
1357    attribute data types do.  (Section 3.3.3 of the recommendation.)
1358 */
1359 static int
is_whitespace_normalized(const XML_Char * s,int is_cdata)1360 is_whitespace_normalized(const XML_Char *s, int is_cdata)
1361 {
1362     int blanks = 0;
1363     int at_start = 1;
1364     while (*s) {
1365         if (*s == XCS(' '))
1366             ++blanks;
1367         else if (*s == XCS('\t') || *s == XCS('\n') || *s == XCS('\r'))
1368             return 0;
1369         else {
1370             if (at_start) {
1371                 at_start = 0;
1372                 if (blanks && !is_cdata)
1373                     /* illegal leading blanks */
1374                     return 0;
1375             }
1376             else if (blanks > 1 && !is_cdata)
1377                 return 0;
1378             blanks = 0;
1379         }
1380         ++s;
1381     }
1382     if (blanks && !is_cdata)
1383         return 0;
1384     return 1;
1385 }
1386 
1387 /* Check the attribute whitespace checker: */
1388 static void
testhelper_is_whitespace_normalized(void)1389 testhelper_is_whitespace_normalized(void)
1390 {
1391     assert(is_whitespace_normalized(XCS("abc"), 0));
1392     assert(is_whitespace_normalized(XCS("abc"), 1));
1393     assert(is_whitespace_normalized(XCS("abc def ghi"), 0));
1394     assert(is_whitespace_normalized(XCS("abc def ghi"), 1));
1395     assert(!is_whitespace_normalized(XCS(" abc def ghi"), 0));
1396     assert(is_whitespace_normalized(XCS(" abc def ghi"), 1));
1397     assert(!is_whitespace_normalized(XCS("abc  def ghi"), 0));
1398     assert(is_whitespace_normalized(XCS("abc  def ghi"), 1));
1399     assert(!is_whitespace_normalized(XCS("abc def ghi "), 0));
1400     assert(is_whitespace_normalized(XCS("abc def ghi "), 1));
1401     assert(!is_whitespace_normalized(XCS(" "), 0));
1402     assert(is_whitespace_normalized(XCS(" "), 1));
1403     assert(!is_whitespace_normalized(XCS("\t"), 0));
1404     assert(!is_whitespace_normalized(XCS("\t"), 1));
1405     assert(!is_whitespace_normalized(XCS("\n"), 0));
1406     assert(!is_whitespace_normalized(XCS("\n"), 1));
1407     assert(!is_whitespace_normalized(XCS("\r"), 0));
1408     assert(!is_whitespace_normalized(XCS("\r"), 1));
1409     assert(!is_whitespace_normalized(XCS("abc\t def"), 1));
1410 }
1411 
1412 static void XMLCALL
check_attr_contains_normalized_whitespace(void * UNUSED_P (userData),const XML_Char * UNUSED_P (name),const XML_Char ** atts)1413 check_attr_contains_normalized_whitespace(void *UNUSED_P(userData),
1414                                           const XML_Char *UNUSED_P(name),
1415                                           const XML_Char **atts)
1416 {
1417     int i;
1418     for (i = 0; atts[i] != NULL; i += 2) {
1419         const XML_Char *attrname = atts[i];
1420         const XML_Char *value = atts[i + 1];
1421         if (xcstrcmp(XCS("attr"), attrname) == 0
1422             || xcstrcmp(XCS("ents"), attrname) == 0
1423             || xcstrcmp(XCS("refs"), attrname) == 0) {
1424             if (!is_whitespace_normalized(value, 0)) {
1425                 char buffer[256];
1426                 sprintf(buffer, "attribute value not normalized: %"
1427                         XML_FMT_STR "='%" XML_FMT_STR "'",
1428                         attrname, value);
1429                 fail(buffer);
1430             }
1431         }
1432     }
1433 }
1434 
START_TEST(test_attr_whitespace_normalization)1435 START_TEST(test_attr_whitespace_normalization)
1436 {
1437     const char *text =
1438         "<!DOCTYPE doc [\n"
1439         "  <!ATTLIST doc\n"
1440         "            attr NMTOKENS #REQUIRED\n"
1441         "            ents ENTITIES #REQUIRED\n"
1442         "            refs IDREFS   #REQUIRED>\n"
1443         "]>\n"
1444         "<doc attr='    a  b c\t\td\te\t' refs=' id-1   \t  id-2\t\t'  \n"
1445         "     ents=' ent-1   \t\r\n"
1446         "            ent-2  ' >\n"
1447         "  <e id='id-1'/>\n"
1448         "  <e id='id-2'/>\n"
1449         "</doc>";
1450 
1451     XML_SetStartElementHandler(parser,
1452                                check_attr_contains_normalized_whitespace);
1453     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
1454         xml_failure(parser);
1455 }
1456 END_TEST
1457 
1458 
1459 /*
1460  * XML declaration tests.
1461  */
1462 
START_TEST(test_xmldecl_misplaced)1463 START_TEST(test_xmldecl_misplaced)
1464 {
1465     expect_failure("\n"
1466                    "<?xml version='1.0'?>\n"
1467                    "<a/>",
1468                    XML_ERROR_MISPLACED_XML_PI,
1469                    "failed to report misplaced XML declaration");
1470 }
1471 END_TEST
1472 
START_TEST(test_xmldecl_invalid)1473 START_TEST(test_xmldecl_invalid)
1474 {
1475     expect_failure("<?xml version='1.0' \xc3\xa7?>\n<doc/>",
1476                    XML_ERROR_XML_DECL,
1477                    "Failed to report invalid XML declaration");
1478 }
1479 END_TEST
1480 
START_TEST(test_xmldecl_missing_attr)1481 START_TEST(test_xmldecl_missing_attr)
1482 {
1483     expect_failure("<?xml ='1.0'?>\n<doc/>\n",
1484                    XML_ERROR_XML_DECL,
1485                    "Failed to report missing XML declaration attribute");
1486 }
1487 END_TEST
1488 
START_TEST(test_xmldecl_missing_value)1489 START_TEST(test_xmldecl_missing_value)
1490 {
1491     expect_failure("<?xml version='1.0' encoding='us-ascii' standalone?>\n"
1492                    "<doc/>",
1493                    XML_ERROR_XML_DECL,
1494                    "Failed to report missing attribute value");
1495 }
1496 END_TEST
1497 
1498 /* Regression test for SF bug #584832. */
1499 static int XMLCALL
UnknownEncodingHandler(void * UNUSED_P (data),const XML_Char * encoding,XML_Encoding * info)1500 UnknownEncodingHandler(void *UNUSED_P(data),const XML_Char *encoding,XML_Encoding *info)
1501 {
1502     if (xcstrcmp(encoding, XCS("unsupported-encoding")) == 0) {
1503         int i;
1504         for (i = 0; i < 256; ++i)
1505             info->map[i] = i;
1506         info->data = NULL;
1507         info->convert = NULL;
1508         info->release = NULL;
1509         return XML_STATUS_OK;
1510     }
1511     return XML_STATUS_ERROR;
1512 }
1513 
START_TEST(test_unknown_encoding_internal_entity)1514 START_TEST(test_unknown_encoding_internal_entity)
1515 {
1516     const char *text =
1517         "<?xml version='1.0' encoding='unsupported-encoding'?>\n"
1518         "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n"
1519         "<test a='&foo;'/>";
1520 
1521     XML_SetUnknownEncodingHandler(parser, UnknownEncodingHandler, NULL);
1522     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
1523         xml_failure(parser);
1524 }
1525 END_TEST
1526 
1527 /* Test unrecognised encoding handler */
dummy_release(void * UNUSED_P (data))1528 static void dummy_release(void *UNUSED_P(data))
1529 {
1530 }
1531 
1532 static int XMLCALL
UnrecognisedEncodingHandler(void * UNUSED_P (data),const XML_Char * UNUSED_P (encoding),XML_Encoding * info)1533 UnrecognisedEncodingHandler(void *UNUSED_P(data),
1534                             const XML_Char *UNUSED_P(encoding),
1535                             XML_Encoding *info)
1536 {
1537     info->data = NULL;
1538     info->convert = NULL;
1539     info->release = dummy_release;
1540     return XML_STATUS_ERROR;
1541 }
1542 
START_TEST(test_unrecognised_encoding_internal_entity)1543 START_TEST(test_unrecognised_encoding_internal_entity)
1544 {
1545     const char *text =
1546         "<?xml version='1.0' encoding='unsupported-encoding'?>\n"
1547         "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n"
1548         "<test a='&foo;'/>";
1549 
1550     XML_SetUnknownEncodingHandler(parser,
1551                                   UnrecognisedEncodingHandler,
1552                                   NULL);
1553     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) != XML_STATUS_ERROR)
1554         fail("Unrecognised encoding not rejected");
1555 }
1556 END_TEST
1557 
1558 /* Regression test for SF bug #620106. */
1559 static int XMLCALL
external_entity_loader(XML_Parser parser,const XML_Char * context,const XML_Char * UNUSED_P (base),const XML_Char * UNUSED_P (systemId),const XML_Char * UNUSED_P (publicId))1560 external_entity_loader(XML_Parser parser,
1561                        const XML_Char *context,
1562                        const XML_Char *UNUSED_P(base),
1563                        const XML_Char *UNUSED_P(systemId),
1564                        const XML_Char *UNUSED_P(publicId))
1565 {
1566     ExtTest *test_data = (ExtTest *)XML_GetUserData(parser);
1567     XML_Parser extparser;
1568 
1569     extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
1570     if (extparser == NULL)
1571         fail("Could not create external entity parser.");
1572     if (test_data->encoding != NULL) {
1573         if (!XML_SetEncoding(extparser, test_data->encoding))
1574             fail("XML_SetEncoding() ignored for external entity");
1575     }
1576     if ( _XML_Parse_SINGLE_BYTES(extparser,
1577                                  test_data->parse_text,
1578                                  strlen(test_data->parse_text),
1579                                  XML_TRUE)
1580           == XML_STATUS_ERROR) {
1581         xml_failure(extparser);
1582         return XML_STATUS_ERROR;
1583     }
1584     XML_ParserFree(extparser);
1585     return XML_STATUS_OK;
1586 }
1587 
START_TEST(test_ext_entity_set_encoding)1588 START_TEST(test_ext_entity_set_encoding)
1589 {
1590     const char *text =
1591         "<!DOCTYPE doc [\n"
1592         "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1593         "]>\n"
1594         "<doc>&en;</doc>";
1595     ExtTest test_data = {
1596         /* This text says it's an unsupported encoding, but it's really
1597            UTF-8, which we tell Expat using XML_SetEncoding().
1598         */
1599         "<?xml encoding='iso-8859-3'?>\xC3\xA9",
1600         XCS("utf-8"),
1601         NULL
1602     };
1603 #ifdef XML_UNICODE
1604     const XML_Char *expected = XCS("\x00e9");
1605 #else
1606     const XML_Char *expected = XCS("\xc3\xa9");
1607 #endif
1608 
1609     XML_SetExternalEntityRefHandler(parser, external_entity_loader);
1610     run_ext_character_check(text, &test_data, expected);
1611 }
1612 END_TEST
1613 
1614 /* Test external entities with no handler */
START_TEST(test_ext_entity_no_handler)1615 START_TEST(test_ext_entity_no_handler)
1616 {
1617     const char *text =
1618         "<!DOCTYPE doc [\n"
1619         "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1620         "]>\n"
1621         "<doc>&en;</doc>";
1622 
1623     XML_SetDefaultHandler(parser, dummy_default_handler);
1624     run_character_check(text, XCS(""));
1625 }
1626 END_TEST
1627 
1628 /* Test UTF-8 BOM is accepted */
START_TEST(test_ext_entity_set_bom)1629 START_TEST(test_ext_entity_set_bom)
1630 {
1631     const char *text =
1632         "<!DOCTYPE doc [\n"
1633         "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1634         "]>\n"
1635         "<doc>&en;</doc>";
1636     ExtTest test_data = {
1637         "\xEF\xBB\xBF" /* BOM */
1638         "<?xml encoding='iso-8859-3'?>"
1639         "\xC3\xA9",
1640         XCS("utf-8"),
1641         NULL
1642     };
1643 #ifdef XML_UNICODE
1644     const XML_Char *expected = XCS("\x00e9");
1645 #else
1646     const XML_Char *expected = XCS("\xc3\xa9");
1647 #endif
1648 
1649     XML_SetExternalEntityRefHandler(parser, external_entity_loader);
1650     run_ext_character_check(text, &test_data, expected);
1651 }
1652 END_TEST
1653 
1654 
1655 /* Test that bad encodings are faulted */
1656 typedef struct ext_faults
1657 {
1658     const char *parse_text;
1659     const char *fail_text;
1660     const XML_Char *encoding;
1661     enum XML_Error error;
1662 } ExtFaults;
1663 
1664 static int XMLCALL
external_entity_faulter(XML_Parser parser,const XML_Char * context,const XML_Char * UNUSED_P (base),const XML_Char * UNUSED_P (systemId),const XML_Char * UNUSED_P (publicId))1665 external_entity_faulter(XML_Parser parser,
1666                         const XML_Char *context,
1667                         const XML_Char *UNUSED_P(base),
1668                         const XML_Char *UNUSED_P(systemId),
1669                         const XML_Char *UNUSED_P(publicId))
1670 {
1671     XML_Parser ext_parser;
1672     ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser);
1673 
1674     ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
1675     if (ext_parser == NULL)
1676         fail("Could not create external entity parser");
1677     if (fault->encoding != NULL) {
1678         if (!XML_SetEncoding(ext_parser, fault->encoding))
1679             fail("XML_SetEncoding failed");
1680     }
1681     if (_XML_Parse_SINGLE_BYTES(ext_parser,
1682                                 fault->parse_text,
1683                                 strlen(fault->parse_text),
1684                                 XML_TRUE) != XML_STATUS_ERROR)
1685         fail(fault->fail_text);
1686     if (XML_GetErrorCode(ext_parser) != fault->error)
1687         xml_failure(ext_parser);
1688 
1689     XML_ParserFree(ext_parser);
1690     return XML_STATUS_ERROR;
1691 }
1692 
START_TEST(test_ext_entity_bad_encoding)1693 START_TEST(test_ext_entity_bad_encoding)
1694 {
1695     const char *text =
1696         "<!DOCTYPE doc [\n"
1697         "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1698         "]>\n"
1699         "<doc>&en;</doc>";
1700     ExtFaults fault = {
1701         "<?xml encoding='iso-8859-3'?>u",
1702         "Unsupported encoding not faulted",
1703         XCS("unknown"),
1704         XML_ERROR_UNKNOWN_ENCODING
1705     };
1706 
1707     XML_SetExternalEntityRefHandler(parser, external_entity_faulter);
1708     XML_SetUserData(parser, &fault);
1709     expect_failure(text,
1710                    XML_ERROR_EXTERNAL_ENTITY_HANDLING,
1711                    "Bad encoding should not have been accepted");
1712 }
1713 END_TEST
1714 
1715 /* Try handing an invalid encoding to an external entity parser */
START_TEST(test_ext_entity_bad_encoding_2)1716 START_TEST(test_ext_entity_bad_encoding_2)
1717 {
1718     const char *text =
1719         "<?xml version='1.0' encoding='us-ascii'?>\n"
1720         "<!DOCTYPE doc SYSTEM 'foo'>\n"
1721         "<doc>&entity;</doc>";
1722     ExtFaults fault = {
1723         "<!ELEMENT doc (#PCDATA)*>",
1724         "Unknown encoding not faulted",
1725         XCS("unknown-encoding"),
1726         XML_ERROR_UNKNOWN_ENCODING
1727     };
1728 
1729     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1730     XML_SetExternalEntityRefHandler(parser, external_entity_faulter);
1731     XML_SetUserData(parser, &fault);
1732     expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
1733                    "Bad encoding not faulted in external entity handler");
1734 }
1735 END_TEST
1736 
1737 /* Test that no error is reported for unknown entities if we don't
1738    read an external subset.  This was fixed in Expat 1.95.5.
1739 */
START_TEST(test_wfc_undeclared_entity_unread_external_subset)1740 START_TEST(test_wfc_undeclared_entity_unread_external_subset) {
1741     const char *text =
1742         "<!DOCTYPE doc SYSTEM 'foo'>\n"
1743         "<doc>&entity;</doc>";
1744 
1745     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
1746         xml_failure(parser);
1747 }
1748 END_TEST
1749 
1750 /* Test that an error is reported for unknown entities if we don't
1751    have an external subset.
1752 */
START_TEST(test_wfc_undeclared_entity_no_external_subset)1753 START_TEST(test_wfc_undeclared_entity_no_external_subset) {
1754     expect_failure("<doc>&entity;</doc>",
1755                    XML_ERROR_UNDEFINED_ENTITY,
1756                    "Parser did not report undefined entity w/out a DTD.");
1757 }
1758 END_TEST
1759 
1760 /* Test that an error is reported for unknown entities if we don't
1761    read an external subset, but have been declared standalone.
1762 */
START_TEST(test_wfc_undeclared_entity_standalone)1763 START_TEST(test_wfc_undeclared_entity_standalone) {
1764     const char *text =
1765         "<?xml version='1.0' encoding='us-ascii' standalone='yes'?>\n"
1766         "<!DOCTYPE doc SYSTEM 'foo'>\n"
1767         "<doc>&entity;</doc>";
1768 
1769     expect_failure(text,
1770                    XML_ERROR_UNDEFINED_ENTITY,
1771                    "Parser did not report undefined entity (standalone).");
1772 }
1773 END_TEST
1774 
1775 /* Test that an error is reported for unknown entities if we have read
1776    an external subset, and standalone is true.
1777 */
START_TEST(test_wfc_undeclared_entity_with_external_subset_standalone)1778 START_TEST(test_wfc_undeclared_entity_with_external_subset_standalone) {
1779     const char *text =
1780         "<?xml version='1.0' encoding='us-ascii' standalone='yes'?>\n"
1781         "<!DOCTYPE doc SYSTEM 'foo'>\n"
1782         "<doc>&entity;</doc>";
1783     ExtTest test_data = {
1784         "<!ELEMENT doc (#PCDATA)*>",
1785         NULL,
1786         NULL
1787     };
1788 
1789     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1790     XML_SetUserData(parser, &test_data);
1791     XML_SetExternalEntityRefHandler(parser, external_entity_loader);
1792     expect_failure(text,
1793                    XML_ERROR_UNDEFINED_ENTITY,
1794                    "Parser did not report undefined entity (external DTD).");
1795 }
1796 END_TEST
1797 
1798 /* Test that external entity handling is not done if the parsing flag
1799  * is set to UNLESS_STANDALONE
1800  */
START_TEST(test_entity_with_external_subset_unless_standalone)1801 START_TEST(test_entity_with_external_subset_unless_standalone) {
1802     const char *text =
1803         "<?xml version='1.0' encoding='us-ascii' standalone='yes'?>\n"
1804         "<!DOCTYPE doc SYSTEM 'foo'>\n"
1805         "<doc>&entity;</doc>";
1806     ExtTest test_data = { "<!ENTITY entity 'bar'>", NULL, NULL };
1807 
1808     XML_SetParamEntityParsing(parser,
1809                               XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE);
1810     XML_SetUserData(parser, &test_data);
1811     XML_SetExternalEntityRefHandler(parser, external_entity_loader);
1812     expect_failure(text,
1813                    XML_ERROR_UNDEFINED_ENTITY,
1814                    "Parser did not report undefined entity");
1815 }
1816 END_TEST
1817 
1818 /* Test that no error is reported for unknown entities if we have read
1819    an external subset, and standalone is false.
1820 */
START_TEST(test_wfc_undeclared_entity_with_external_subset)1821 START_TEST(test_wfc_undeclared_entity_with_external_subset) {
1822     const char *text =
1823         "<?xml version='1.0' encoding='us-ascii'?>\n"
1824         "<!DOCTYPE doc SYSTEM 'foo'>\n"
1825         "<doc>&entity;</doc>";
1826     ExtTest test_data = {
1827         "<!ELEMENT doc (#PCDATA)*>",
1828         NULL,
1829         NULL
1830     };
1831 
1832     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1833     XML_SetExternalEntityRefHandler(parser, external_entity_loader);
1834     run_ext_character_check(text, &test_data, XCS(""));
1835 }
1836 END_TEST
1837 
1838 /* Test that an error is reported if our NotStandalone handler fails */
1839 static int XMLCALL
reject_not_standalone_handler(void * UNUSED_P (userData))1840 reject_not_standalone_handler(void *UNUSED_P(userData))
1841 {
1842     return XML_STATUS_ERROR;
1843 }
1844 
START_TEST(test_not_standalone_handler_reject)1845 START_TEST(test_not_standalone_handler_reject)
1846 {
1847     const char *text =
1848         "<?xml version='1.0' encoding='us-ascii'?>\n"
1849         "<!DOCTYPE doc SYSTEM 'foo'>\n"
1850         "<doc>&entity;</doc>";
1851     ExtTest test_data = {
1852         "<!ELEMENT doc (#PCDATA)*>",
1853         NULL,
1854         NULL
1855     };
1856 
1857     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1858     XML_SetUserData(parser, &test_data);
1859     XML_SetExternalEntityRefHandler(parser, external_entity_loader);
1860     XML_SetNotStandaloneHandler(parser, reject_not_standalone_handler);
1861     expect_failure(text, XML_ERROR_NOT_STANDALONE,
1862                    "NotStandalone handler failed to reject");
1863 
1864     /* Try again but without external entity handling */
1865     XML_ParserReset(parser, NULL);
1866     XML_SetNotStandaloneHandler(parser, reject_not_standalone_handler);
1867     expect_failure(text, XML_ERROR_NOT_STANDALONE,
1868                    "NotStandalone handler failed to reject");
1869 }
1870 END_TEST
1871 
1872 /* Test that no error is reported if our NotStandalone handler succeeds */
1873 static int XMLCALL
accept_not_standalone_handler(void * UNUSED_P (userData))1874 accept_not_standalone_handler(void *UNUSED_P(userData))
1875 {
1876     return XML_STATUS_OK;
1877 }
1878 
START_TEST(test_not_standalone_handler_accept)1879 START_TEST(test_not_standalone_handler_accept)
1880 {
1881     const char *text =
1882         "<?xml version='1.0' encoding='us-ascii'?>\n"
1883         "<!DOCTYPE doc SYSTEM 'foo'>\n"
1884         "<doc>&entity;</doc>";
1885     ExtTest test_data = {
1886         "<!ELEMENT doc (#PCDATA)*>",
1887         NULL,
1888         NULL
1889     };
1890 
1891     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1892     XML_SetExternalEntityRefHandler(parser, external_entity_loader);
1893     XML_SetNotStandaloneHandler(parser, accept_not_standalone_handler);
1894     run_ext_character_check(text, &test_data, XCS(""));
1895 
1896     /* Repeat wtihout the external entity handler */
1897     XML_ParserReset(parser, NULL);
1898     XML_SetNotStandaloneHandler(parser, accept_not_standalone_handler);
1899     run_character_check(text, XCS(""));
1900 }
1901 END_TEST
1902 
START_TEST(test_wfc_no_recursive_entity_refs)1903 START_TEST(test_wfc_no_recursive_entity_refs)
1904 {
1905     const char *text =
1906         "<!DOCTYPE doc [\n"
1907         "  <!ENTITY entity '&#38;entity;'>\n"
1908         "]>\n"
1909         "<doc>&entity;</doc>";
1910 
1911     expect_failure(text,
1912                    XML_ERROR_RECURSIVE_ENTITY_REF,
1913                    "Parser did not report recursive entity reference.");
1914 }
1915 END_TEST
1916 
1917 /* Test incomplete external entities are faulted */
START_TEST(test_ext_entity_invalid_parse)1918 START_TEST(test_ext_entity_invalid_parse)
1919 {
1920     const char *text =
1921         "<!DOCTYPE doc [\n"
1922         "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1923         "]>\n"
1924         "<doc>&en;</doc>";
1925     const ExtFaults faults[] = {
1926         {
1927             "<",
1928             "Incomplete element declaration not faulted",
1929             NULL,
1930             XML_ERROR_UNCLOSED_TOKEN
1931         },
1932         {
1933             "<\xe2\x82", /* First two bytes of a three-byte char */
1934             "Incomplete character not faulted",
1935             NULL,
1936             XML_ERROR_PARTIAL_CHAR
1937         },
1938         {
1939             "<tag>\xe2\x82",
1940             "Incomplete character in CDATA not faulted",
1941             NULL,
1942             XML_ERROR_PARTIAL_CHAR
1943         },
1944         { NULL, NULL, NULL, XML_ERROR_NONE }
1945     };
1946     const ExtFaults *fault = faults;
1947 
1948     for (; fault->parse_text != NULL; fault++) {
1949         XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1950         XML_SetExternalEntityRefHandler(parser, external_entity_faulter);
1951         XML_SetUserData(parser, (void *)fault);
1952         expect_failure(text,
1953                        XML_ERROR_EXTERNAL_ENTITY_HANDLING,
1954                        "Parser did not report external entity error");
1955         XML_ParserReset(parser, NULL);
1956     }
1957 }
1958 END_TEST
1959 
1960 
1961 /* Regression test for SF bug #483514. */
START_TEST(test_dtd_default_handling)1962 START_TEST(test_dtd_default_handling)
1963 {
1964     const char *text =
1965         "<!DOCTYPE doc [\n"
1966         "<!ENTITY e SYSTEM 'http://example.org/e'>\n"
1967         "<!NOTATION n SYSTEM 'http://example.org/n'>\n"
1968         "<!ELEMENT doc EMPTY>\n"
1969         "<!ATTLIST doc a CDATA #IMPLIED>\n"
1970         "<?pi in dtd?>\n"
1971         "<!--comment in dtd-->\n"
1972         "]><doc/>";
1973 
1974     XML_SetDefaultHandler(parser, accumulate_characters);
1975     XML_SetStartDoctypeDeclHandler(parser, dummy_start_doctype_handler);
1976     XML_SetEndDoctypeDeclHandler(parser, dummy_end_doctype_handler);
1977     XML_SetEntityDeclHandler(parser, dummy_entity_decl_handler);
1978     XML_SetNotationDeclHandler(parser, dummy_notation_decl_handler);
1979     XML_SetElementDeclHandler(parser, dummy_element_decl_handler);
1980     XML_SetAttlistDeclHandler(parser, dummy_attlist_decl_handler);
1981     XML_SetProcessingInstructionHandler(parser, dummy_pi_handler);
1982     XML_SetCommentHandler(parser, dummy_comment_handler);
1983     XML_SetStartCdataSectionHandler(parser, dummy_start_cdata_handler);
1984     XML_SetEndCdataSectionHandler(parser, dummy_end_cdata_handler);
1985     run_character_check(text, XCS("\n\n\n\n\n\n\n<doc/>"));
1986 }
1987 END_TEST
1988 
1989 /* Test handling of attribute declarations */
1990 typedef struct AttTest {
1991     const char *definition;
1992     const XML_Char *element_name;
1993     const XML_Char *attr_name;
1994     const XML_Char *attr_type;
1995     const XML_Char *default_value;
1996     int is_required;
1997 } AttTest;
1998 
1999 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)2000 verify_attlist_decl_handler(void *userData,
2001                             const XML_Char *element_name,
2002                             const XML_Char *attr_name,
2003                             const XML_Char *attr_type,
2004                             const XML_Char *default_value,
2005                             int is_required)
2006 {
2007     AttTest *at = (AttTest *)userData;
2008 
2009     if (xcstrcmp(element_name, at->element_name))
2010         fail("Unexpected element name in attribute declaration");
2011     if (xcstrcmp(attr_name, at->attr_name))
2012         fail("Unexpected attribute name in attribute declaration");
2013     if (xcstrcmp(attr_type, at->attr_type))
2014         fail("Unexpected attribute type in attribute declaration");
2015     if ((default_value == NULL && at->default_value != NULL) ||
2016         (default_value != NULL && at->default_value == NULL) ||
2017         (default_value != NULL && xcstrcmp(default_value, at->default_value)))
2018         fail("Unexpected default value in attribute declaration");
2019     if (is_required != at->is_required)
2020         fail("Requirement mismatch in attribute declaration");
2021 }
2022 
START_TEST(test_dtd_attr_handling)2023 START_TEST(test_dtd_attr_handling)
2024 {
2025     const char *prolog =
2026         "<!DOCTYPE doc [\n"
2027         "<!ELEMENT doc EMPTY>\n";
2028     AttTest attr_data[] = {
2029         {
2030             "<!ATTLIST doc a ( one | two | three ) #REQUIRED>\n"
2031             "]>"
2032             "<doc a='two'/>",
2033             XCS("doc"),
2034             XCS("a"),
2035             XCS("(one|two|three)"), /* Extraneous spaces will be removed */
2036             NULL,
2037             XML_TRUE
2038         },
2039         {
2040             "<!NOTATION foo SYSTEM 'http://example.org/foo'>\n"
2041             "<!ATTLIST doc a NOTATION (foo) #IMPLIED>\n"
2042             "]>"
2043             "<doc/>",
2044             XCS("doc"),
2045             XCS("a"),
2046             XCS("NOTATION(foo)"),
2047             NULL,
2048             XML_FALSE
2049         },
2050         {
2051             "<!ATTLIST doc a NOTATION (foo) 'bar'>\n"
2052             "]>"
2053             "<doc/>",
2054             XCS("doc"),
2055             XCS("a"),
2056             XCS("NOTATION(foo)"),
2057             XCS("bar"),
2058             XML_FALSE
2059         },
2060         {
2061             "<!ATTLIST doc a CDATA '\xdb\xb2'>\n"
2062             "]>"
2063             "<doc/>",
2064             XCS("doc"),
2065             XCS("a"),
2066             XCS("CDATA"),
2067 #ifdef XML_UNICODE
2068             XCS("\x06f2"),
2069 #else
2070             XCS("\xdb\xb2"),
2071 #endif
2072             XML_FALSE
2073         },
2074         { NULL, NULL, NULL, NULL, NULL, XML_FALSE }
2075     };
2076     AttTest *test;
2077 
2078     for (test = attr_data; test->definition != NULL; test++) {
2079         XML_SetAttlistDeclHandler(parser, verify_attlist_decl_handler);
2080         XML_SetUserData(parser, test);
2081         if (_XML_Parse_SINGLE_BYTES(parser, prolog, strlen(prolog),
2082                                     XML_FALSE) == XML_STATUS_ERROR)
2083             xml_failure(parser);
2084         if (_XML_Parse_SINGLE_BYTES(parser,
2085                                     test->definition,
2086                                     strlen(test->definition),
2087                                     XML_TRUE) == XML_STATUS_ERROR)
2088             xml_failure(parser);
2089         XML_ParserReset(parser, NULL);
2090     }
2091 }
2092 END_TEST
2093 
2094 /* See related SF bug #673791.
2095    When namespace processing is enabled, setting the namespace URI for
2096    a prefix is not allowed; this test ensures that it *is* allowed
2097    when namespace processing is not enabled.
2098    (See Namespaces in XML, section 2.)
2099 */
START_TEST(test_empty_ns_without_namespaces)2100 START_TEST(test_empty_ns_without_namespaces)
2101 {
2102     const char *text =
2103         "<doc xmlns:prefix='http://example.org/'>\n"
2104         "  <e xmlns:prefix=''/>\n"
2105         "</doc>";
2106 
2107     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
2108         xml_failure(parser);
2109 }
2110 END_TEST
2111 
2112 /* Regression test for SF bug #824420.
2113    Checks that an xmlns:prefix attribute set in an attribute's default
2114    value isn't misinterpreted.
2115 */
START_TEST(test_ns_in_attribute_default_without_namespaces)2116 START_TEST(test_ns_in_attribute_default_without_namespaces)
2117 {
2118     const char *text =
2119         "<!DOCTYPE e:element [\n"
2120         "  <!ATTLIST e:element\n"
2121         "    xmlns:e CDATA 'http://example.org/'>\n"
2122         "      ]>\n"
2123         "<e:element/>";
2124 
2125     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
2126         xml_failure(parser);
2127 }
2128 END_TEST
2129 
2130 static const char *long_character_data_text =
2131     "<?xml version='1.0' encoding='iso-8859-1'?><s>"
2132     "012345678901234567890123456789012345678901234567890123456789"
2133     "012345678901234567890123456789012345678901234567890123456789"
2134     "012345678901234567890123456789012345678901234567890123456789"
2135     "012345678901234567890123456789012345678901234567890123456789"
2136     "012345678901234567890123456789012345678901234567890123456789"
2137     "012345678901234567890123456789012345678901234567890123456789"
2138     "012345678901234567890123456789012345678901234567890123456789"
2139     "012345678901234567890123456789012345678901234567890123456789"
2140     "012345678901234567890123456789012345678901234567890123456789"
2141     "012345678901234567890123456789012345678901234567890123456789"
2142     "012345678901234567890123456789012345678901234567890123456789"
2143     "012345678901234567890123456789012345678901234567890123456789"
2144     "012345678901234567890123456789012345678901234567890123456789"
2145     "012345678901234567890123456789012345678901234567890123456789"
2146     "012345678901234567890123456789012345678901234567890123456789"
2147     "012345678901234567890123456789012345678901234567890123456789"
2148     "012345678901234567890123456789012345678901234567890123456789"
2149     "012345678901234567890123456789012345678901234567890123456789"
2150     "012345678901234567890123456789012345678901234567890123456789"
2151     "012345678901234567890123456789012345678901234567890123456789"
2152     "</s>";
2153 
2154 static XML_Bool resumable = XML_FALSE;
2155 
2156 static void
clearing_aborting_character_handler(void * UNUSED_P (userData),const XML_Char * UNUSED_P (s),int UNUSED_P (len))2157 clearing_aborting_character_handler(void *UNUSED_P(userData),
2158                                     const XML_Char *UNUSED_P(s), int UNUSED_P(len))
2159 {
2160     XML_StopParser(parser, resumable);
2161     XML_SetCharacterDataHandler(parser, NULL);
2162 }
2163 
2164 /* Regression test for SF bug #1515266: missing check of stopped
2165    parser in doContext() 'for' loop. */
START_TEST(test_stop_parser_between_char_data_calls)2166 START_TEST(test_stop_parser_between_char_data_calls)
2167 {
2168     /* The sample data must be big enough that there are two calls to
2169        the character data handler from within the inner "for" loop of
2170        the XML_TOK_DATA_CHARS case in doContent(), and the character
2171        handler must stop the parser and clear the character data
2172        handler.
2173     */
2174     const char *text = long_character_data_text;
2175 
2176     XML_SetCharacterDataHandler(parser, clearing_aborting_character_handler);
2177     resumable = XML_FALSE;
2178     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) != XML_STATUS_ERROR)
2179         xml_failure(parser);
2180     if (XML_GetErrorCode(parser) != XML_ERROR_ABORTED)
2181         xml_failure(parser);
2182 }
2183 END_TEST
2184 
2185 /* Regression test for SF bug #1515266: missing check of stopped
2186    parser in doContext() 'for' loop. */
START_TEST(test_suspend_parser_between_char_data_calls)2187 START_TEST(test_suspend_parser_between_char_data_calls)
2188 {
2189     /* The sample data must be big enough that there are two calls to
2190        the character data handler from within the inner "for" loop of
2191        the XML_TOK_DATA_CHARS case in doContent(), and the character
2192        handler must stop the parser and clear the character data
2193        handler.
2194     */
2195     const char *text = long_character_data_text;
2196 
2197     XML_SetCharacterDataHandler(parser, clearing_aborting_character_handler);
2198     resumable = XML_TRUE;
2199     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) != XML_STATUS_SUSPENDED)
2200         xml_failure(parser);
2201     if (XML_GetErrorCode(parser) != XML_ERROR_NONE)
2202         xml_failure(parser);
2203     /* Try parsing directly */
2204     if (XML_Parse(parser, text, strlen(text), XML_TRUE) != XML_STATUS_ERROR)
2205         fail("Attempt to continue parse while suspended not faulted");
2206     if (XML_GetErrorCode(parser) != XML_ERROR_SUSPENDED)
2207         fail("Suspended parse not faulted with correct error");
2208 }
2209 END_TEST
2210 
2211 
2212 static XML_Bool abortable = XML_FALSE;
2213 
2214 static void
parser_stop_character_handler(void * UNUSED_P (userData),const XML_Char * UNUSED_P (s),int UNUSED_P (len))2215 parser_stop_character_handler(void *UNUSED_P(userData),
2216                               const XML_Char *UNUSED_P(s),
2217                               int UNUSED_P(len))
2218 {
2219     XML_StopParser(parser, resumable);
2220     XML_SetCharacterDataHandler(parser, NULL);
2221     if (!resumable) {
2222         /* Check that aborting an aborted parser is faulted */
2223         if (XML_StopParser(parser, XML_FALSE) != XML_STATUS_ERROR)
2224             fail("Aborting aborted parser not faulted");
2225         if (XML_GetErrorCode(parser) != XML_ERROR_FINISHED)
2226             xml_failure(parser);
2227     } else if (abortable) {
2228         /* Check that aborting a suspended parser works */
2229         if (XML_StopParser(parser, XML_FALSE) == XML_STATUS_ERROR)
2230             xml_failure(parser);
2231     } else {
2232         /* Check that suspending a suspended parser works */
2233         if (XML_StopParser(parser, XML_TRUE) != XML_STATUS_ERROR)
2234             fail("Suspending suspended parser not faulted");
2235         if (XML_GetErrorCode(parser) != XML_ERROR_SUSPENDED)
2236             xml_failure(parser);
2237     }
2238 }
2239 
2240 /* Test repeated calls to XML_StopParser are handled correctly */
START_TEST(test_repeated_stop_parser_between_char_data_calls)2241 START_TEST(test_repeated_stop_parser_between_char_data_calls)
2242 {
2243     const char *text = long_character_data_text;
2244 
2245     XML_SetCharacterDataHandler(parser, parser_stop_character_handler);
2246     resumable = XML_FALSE;
2247     abortable = XML_FALSE;
2248     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
2249                                 XML_TRUE) != XML_STATUS_ERROR)
2250         fail("Failed to double-stop parser");
2251 
2252     XML_ParserReset(parser, NULL);
2253     XML_SetCharacterDataHandler(parser, parser_stop_character_handler);
2254     resumable = XML_TRUE;
2255     abortable = XML_FALSE;
2256     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
2257                                 XML_TRUE) != XML_STATUS_SUSPENDED)
2258         fail("Failed to double-suspend parser");
2259 
2260     XML_ParserReset(parser, NULL);
2261     XML_SetCharacterDataHandler(parser, parser_stop_character_handler);
2262     resumable = XML_TRUE;
2263     abortable = XML_TRUE;
2264     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
2265                                 XML_TRUE) != XML_STATUS_ERROR)
2266         fail("Failed to suspend-abort parser");
2267 }
2268 END_TEST
2269 
2270 
START_TEST(test_good_cdata_ascii)2271 START_TEST(test_good_cdata_ascii)
2272 {
2273     const char *text = "<a><![CDATA[<greeting>Hello, world!</greeting>]]></a>";
2274     const XML_Char *expected = XCS("<greeting>Hello, world!</greeting>");
2275 
2276     CharData storage;
2277     CharData_Init(&storage);
2278     XML_SetUserData(parser, &storage);
2279     XML_SetCharacterDataHandler(parser, accumulate_characters);
2280     /* Add start and end handlers for coverage */
2281     XML_SetStartCdataSectionHandler(parser, dummy_start_cdata_handler);
2282     XML_SetEndCdataSectionHandler(parser, dummy_end_cdata_handler);
2283 
2284     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
2285         xml_failure(parser);
2286     CharData_CheckXMLChars(&storage, expected);
2287 
2288     /* Try again, this time with a default handler */
2289     XML_ParserReset(parser, NULL);
2290     CharData_Init(&storage);
2291     XML_SetUserData(parser, &storage);
2292     XML_SetCharacterDataHandler(parser, accumulate_characters);
2293     XML_SetDefaultHandler(parser, dummy_default_handler);
2294 
2295     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
2296         xml_failure(parser);
2297     CharData_CheckXMLChars(&storage, expected);
2298 }
2299 END_TEST
2300 
START_TEST(test_good_cdata_utf16)2301 START_TEST(test_good_cdata_utf16)
2302 {
2303     /* Test data is:
2304      *   <?xml version='1.0' encoding='utf-16'?>
2305      *   <a><![CDATA[hello]]></a>
2306      */
2307     const char text[] =
2308             "\0<\0?\0x\0m\0l\0"
2309                 " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2310                 " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0""1\0""6\0'"
2311                 "\0?\0>\0\n"
2312             "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0[\0h\0e\0l\0l\0o\0]\0]\0>\0<\0/\0a\0>";
2313     const XML_Char *expected = XCS("hello");
2314 
2315     CharData storage;
2316     CharData_Init(&storage);
2317     XML_SetUserData(parser, &storage);
2318     XML_SetCharacterDataHandler(parser, accumulate_characters);
2319 
2320     if (_XML_Parse_SINGLE_BYTES(parser, text, sizeof(text) - 1, XML_TRUE) == XML_STATUS_ERROR)
2321         xml_failure(parser);
2322     CharData_CheckXMLChars(&storage, expected);
2323 }
2324 END_TEST
2325 
START_TEST(test_good_cdata_utf16_le)2326 START_TEST(test_good_cdata_utf16_le)
2327 {
2328     /* Test data is:
2329      *   <?xml version='1.0' encoding='utf-16'?>
2330      *   <a><![CDATA[hello]]></a>
2331      */
2332     const char text[] =
2333             "<\0?\0x\0m\0l\0"
2334                 " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2335                 " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0""1\0""6\0'"
2336                 "\0?\0>\0\n"
2337             "\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";
2338     const XML_Char *expected = XCS("hello");
2339 
2340     CharData storage;
2341     CharData_Init(&storage);
2342     XML_SetUserData(parser, &storage);
2343     XML_SetCharacterDataHandler(parser, accumulate_characters);
2344 
2345     if (_XML_Parse_SINGLE_BYTES(parser, text, sizeof(text) - 1, XML_TRUE) == XML_STATUS_ERROR)
2346         xml_failure(parser);
2347     CharData_CheckXMLChars(&storage, expected);
2348 }
2349 END_TEST
2350 
2351 /* Test UTF16 conversion of a long cdata string */
2352 
2353 /* 16 characters: handy macro to reduce visual clutter */
2354 #define A_TO_P_IN_UTF16 "\0A\0B\0C\0D\0E\0F\0G\0H\0I\0J\0K\0L\0M\0N\0O\0P"
2355 
START_TEST(test_long_cdata_utf16)2356 START_TEST(test_long_cdata_utf16)
2357 {
2358     /* Test data is:
2359      * <?xlm version='1.0' encoding='utf-16'?>
2360      * <a><![CDATA[
2361      * ABCDEFGHIJKLMNOP
2362      * ]]></a>
2363      */
2364     const char text[] =
2365         "\0<\0?\0x\0m\0l\0 "
2366         "\0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0 "
2367         "\0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0\x31\0\x36\0'\0?\0>"
2368         "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0["
2369         /* 64 characters per line */
2370         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2371         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2372         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2373         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2374         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2375         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2376         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2377         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2378         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2379         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2380         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2381         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2382         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2383         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2384         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2385         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2386         A_TO_P_IN_UTF16
2387         "\0]\0]\0>\0<\0/\0a\0>";
2388     const XML_Char *expected =
2389         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2390         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2391         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2392         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2393         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2394         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2395         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2396         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2397         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2398         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2399         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2400         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2401         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2402         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2403         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2404         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2405         XCS("ABCDEFGHIJKLMNOP";)
2406     CharData storage;
2407     void *buffer;
2408 
2409     CharData_Init(&storage);
2410     XML_SetUserData(parser, &storage);
2411     XML_SetCharacterDataHandler(parser, accumulate_characters);
2412     buffer = XML_GetBuffer(parser, sizeof(text) - 1);
2413     if (buffer == NULL)
2414         fail("Could not allocate parse buffer");
2415     memcpy(buffer, text, sizeof(text) - 1);
2416     if (XML_ParseBuffer(parser,
2417                         sizeof(text) - 1,
2418                         XML_TRUE) == XML_STATUS_ERROR)
2419         xml_failure(parser);
2420     CharData_CheckXMLChars(&storage, expected);
2421 }
2422 END_TEST
2423 
2424 /* Test handling of multiple unit UTF-16 characters */
START_TEST(test_multichar_cdata_utf16)2425 START_TEST(test_multichar_cdata_utf16)
2426 {
2427     /* Test data is:
2428      *   <?xml version='1.0' encoding='utf-16'?>
2429      *   <a><![CDATA[{MINIM}{CROTCHET}]]></a>
2430      *
2431      * where {MINIM} is U+1d15e (a minim or half-note)
2432      *   UTF-16: 0xd834 0xdd5e
2433      *   UTF-8:  0xf0 0x9d 0x85 0x9e
2434      * and {CROTCHET} is U+1d15f (a crotchet or quarter-note)
2435      *   UTF-16: 0xd834 0xdd5f
2436      *   UTF-8:  0xf0 0x9d 0x85 0x9f
2437      */
2438     const char text[] =
2439         "\0<\0?\0x\0m\0l\0"
2440         " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2441         " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0""1\0""6\0'"
2442         "\0?\0>\0\n"
2443         "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0["
2444         "\xd8\x34\xdd\x5e\xd8\x34\xdd\x5f"
2445         "\0]\0]\0>\0<\0/\0a\0>";
2446 #ifdef XML_UNICODE
2447     const XML_Char *expected = XCS("\xd834\xdd5e\xd834\xdd5f");
2448 #else
2449     const XML_Char *expected = XCS("\xf0\x9d\x85\x9e\xf0\x9d\x85\x9f");
2450 #endif
2451     CharData storage;
2452 
2453     CharData_Init(&storage);
2454     XML_SetUserData(parser, &storage);
2455     XML_SetCharacterDataHandler(parser, accumulate_characters);
2456 
2457     if (_XML_Parse_SINGLE_BYTES(parser, text, sizeof(text) - 1, XML_TRUE) == XML_STATUS_ERROR)
2458         xml_failure(parser);
2459     CharData_CheckXMLChars(&storage, expected);
2460 }
2461 END_TEST
2462 
2463 /* Test that an element name with a UTF-16 surrogate pair is rejected */
START_TEST(test_utf16_bad_surrogate_pair)2464 START_TEST(test_utf16_bad_surrogate_pair)
2465 {
2466     /* Test data is:
2467      *   <?xml version='1.0' encoding='utf-16'?>
2468      *   <a><![CDATA[{BADLINB}]]></a>
2469      *
2470      * where {BADLINB} is U+10000 (the first Linear B character)
2471      * with the UTF-16 surrogate pair in the wrong order, i.e.
2472      *   0xdc00 0xd800
2473      */
2474     const char text[] =
2475         "\0<\0?\0x\0m\0l\0"
2476         " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2477         " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0""1\0""6\0'"
2478         "\0?\0>\0\n"
2479         "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0["
2480         "\xdc\x00\xd8\x00"
2481         "\0]\0]\0>\0<\0/\0a\0>";
2482 
2483     if (_XML_Parse_SINGLE_BYTES(parser, text, sizeof(text) - 1,
2484                                 XML_TRUE) != XML_STATUS_ERROR)
2485         fail("Reversed UTF-16 surrogate pair not faulted");
2486     if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN)
2487         xml_failure(parser);
2488 }
2489 END_TEST
2490 
2491 
START_TEST(test_bad_cdata)2492 START_TEST(test_bad_cdata)
2493 {
2494     struct CaseData {
2495         const char *text;
2496         enum XML_Error expectedError;
2497     };
2498 
2499     struct CaseData cases[] = {
2500         {"<a><", XML_ERROR_UNCLOSED_TOKEN},
2501         {"<a><!", XML_ERROR_UNCLOSED_TOKEN},
2502         {"<a><![", XML_ERROR_UNCLOSED_TOKEN},
2503         {"<a><![C", XML_ERROR_UNCLOSED_TOKEN},
2504         {"<a><![CD", XML_ERROR_UNCLOSED_TOKEN},
2505         {"<a><![CDA", XML_ERROR_UNCLOSED_TOKEN},
2506         {"<a><![CDAT", XML_ERROR_UNCLOSED_TOKEN},
2507         {"<a><![CDATA", XML_ERROR_UNCLOSED_TOKEN},
2508 
2509         {"<a><![CDATA[", XML_ERROR_UNCLOSED_CDATA_SECTION},
2510         {"<a><![CDATA[]", XML_ERROR_UNCLOSED_CDATA_SECTION},
2511         {"<a><![CDATA[]]", XML_ERROR_UNCLOSED_CDATA_SECTION},
2512 
2513         {"<a><!<a/>", XML_ERROR_INVALID_TOKEN},
2514         {"<a><![<a/>", XML_ERROR_UNCLOSED_TOKEN}, /* ?! */
2515         {"<a><![C<a/>", XML_ERROR_UNCLOSED_TOKEN}, /* ?! */
2516         {"<a><![CD<a/>", XML_ERROR_INVALID_TOKEN},
2517         {"<a><![CDA<a/>", XML_ERROR_INVALID_TOKEN},
2518         {"<a><![CDAT<a/>", XML_ERROR_INVALID_TOKEN},
2519         {"<a><![CDATA<a/>", XML_ERROR_INVALID_TOKEN},
2520 
2521         {"<a><![CDATA[<a/>", XML_ERROR_UNCLOSED_CDATA_SECTION},
2522         {"<a><![CDATA[]<a/>", XML_ERROR_UNCLOSED_CDATA_SECTION},
2523         {"<a><![CDATA[]]<a/>", XML_ERROR_UNCLOSED_CDATA_SECTION}
2524     };
2525 
2526     size_t i = 0;
2527     for (; i < sizeof(cases) / sizeof(struct CaseData); i++) {
2528         const enum XML_Status actualStatus = _XML_Parse_SINGLE_BYTES(
2529                 parser, cases[i].text, strlen(cases[i].text), XML_TRUE);
2530         const enum XML_Error actualError = XML_GetErrorCode(parser);
2531 
2532         assert(actualStatus == XML_STATUS_ERROR);
2533 
2534         if (actualError != cases[i].expectedError) {
2535             char message[100];
2536             sprintf(message, "Expected error %d but got error %d for case %u: \"%s\"\n",
2537                     cases[i].expectedError, actualError, (unsigned int)i + 1, cases[i].text);
2538             fail(message);
2539         }
2540 
2541         XML_ParserReset(parser, NULL);
2542     }
2543 }
2544 END_TEST
2545 
2546 /* Test failures in UTF-16 CDATA */
START_TEST(test_bad_cdata_utf16)2547 START_TEST(test_bad_cdata_utf16)
2548 {
2549     struct CaseData {
2550         size_t text_bytes;
2551         const char *text;
2552         enum XML_Error expected_error;
2553     };
2554 
2555     const char prolog[] =
2556         "\0<\0?\0x\0m\0l\0"
2557         " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2558         " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0""1\0""6\0'"
2559         "\0?\0>\0\n"
2560         "\0<\0a\0>";
2561     struct CaseData cases[] = {
2562         {1, "\0", XML_ERROR_UNCLOSED_TOKEN},
2563         {2, "\0<", XML_ERROR_UNCLOSED_TOKEN},
2564         {3, "\0<\0", XML_ERROR_UNCLOSED_TOKEN},
2565         {4, "\0<\0!", XML_ERROR_UNCLOSED_TOKEN},
2566         {5, "\0<\0!\0", XML_ERROR_UNCLOSED_TOKEN},
2567         {6, "\0<\0!\0[", XML_ERROR_UNCLOSED_TOKEN},
2568         {7, "\0<\0!\0[\0", XML_ERROR_UNCLOSED_TOKEN},
2569         {8, "\0<\0!\0[\0C", XML_ERROR_UNCLOSED_TOKEN},
2570         {9, "\0<\0!\0[\0C\0", XML_ERROR_UNCLOSED_TOKEN},
2571         {10, "\0<\0!\0[\0C\0D", XML_ERROR_UNCLOSED_TOKEN},
2572         {11, "\0<\0!\0[\0C\0D\0", XML_ERROR_UNCLOSED_TOKEN},
2573         {12, "\0<\0!\0[\0C\0D\0A", XML_ERROR_UNCLOSED_TOKEN},
2574         {13, "\0<\0!\0[\0C\0D\0A\0", XML_ERROR_UNCLOSED_TOKEN},
2575         {14, "\0<\0!\0[\0C\0D\0A\0T", XML_ERROR_UNCLOSED_TOKEN},
2576         {15, "\0<\0!\0[\0C\0D\0A\0T\0", XML_ERROR_UNCLOSED_TOKEN},
2577         {16, "\0<\0!\0[\0C\0D\0A\0T\0A", XML_ERROR_UNCLOSED_TOKEN},
2578         {17, "\0<\0!\0[\0C\0D\0A\0T\0A\0", XML_ERROR_UNCLOSED_TOKEN},
2579         {18, "\0<\0!\0[\0C\0D\0A\0T\0A\0[",
2580          XML_ERROR_UNCLOSED_CDATA_SECTION},
2581         {19, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0",
2582          XML_ERROR_UNCLOSED_CDATA_SECTION},
2583         {20, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z",
2584          XML_ERROR_UNCLOSED_CDATA_SECTION},
2585         /* Now add a four-byte UTF-16 character */
2586         {21, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8",
2587          XML_ERROR_UNCLOSED_CDATA_SECTION},
2588         {22, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8\x34",
2589          XML_ERROR_PARTIAL_CHAR},
2590         {23, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8\x34\xdd",
2591          XML_ERROR_PARTIAL_CHAR},
2592         {24, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8\x34\xdd\x5e",
2593          XML_ERROR_UNCLOSED_CDATA_SECTION}
2594     };
2595     size_t i;
2596 
2597     for (i = 0; i < sizeof(cases)/sizeof(struct CaseData); i++) {
2598         enum XML_Status actual_status;
2599         enum XML_Error actual_error;
2600 
2601         if (_XML_Parse_SINGLE_BYTES(parser, prolog, sizeof(prolog)-1,
2602                                     XML_FALSE) == XML_STATUS_ERROR)
2603             xml_failure(parser);
2604         actual_status = _XML_Parse_SINGLE_BYTES(parser,
2605                                                 cases[i].text,
2606                                                 cases[i].text_bytes,
2607                                                 XML_TRUE);
2608         assert(actual_status == XML_STATUS_ERROR);
2609         actual_error = XML_GetErrorCode(parser);
2610         if (actual_error != cases[i].expected_error) {
2611             char message[1024];
2612 
2613             sprintf(message,
2614                     "Expected error %d (%" XML_FMT_STR
2615                     "), got %d (%" XML_FMT_STR ") for case %lu\n",
2616                     cases[i].expected_error,
2617                     XML_ErrorString(cases[i].expected_error),
2618                     actual_error,
2619                     XML_ErrorString(actual_error),
2620                     (long unsigned)(i+1));
2621             fail(message);
2622         }
2623         XML_ParserReset(parser, NULL);
2624     }
2625 }
2626 END_TEST
2627 
2628 static const char *long_cdata_text =
2629     "<s><![CDATA["
2630     "012345678901234567890123456789012345678901234567890123456789"
2631     "012345678901234567890123456789012345678901234567890123456789"
2632     "012345678901234567890123456789012345678901234567890123456789"
2633     "012345678901234567890123456789012345678901234567890123456789"
2634     "012345678901234567890123456789012345678901234567890123456789"
2635     "012345678901234567890123456789012345678901234567890123456789"
2636     "012345678901234567890123456789012345678901234567890123456789"
2637     "012345678901234567890123456789012345678901234567890123456789"
2638     "012345678901234567890123456789012345678901234567890123456789"
2639     "012345678901234567890123456789012345678901234567890123456789"
2640     "012345678901234567890123456789012345678901234567890123456789"
2641     "012345678901234567890123456789012345678901234567890123456789"
2642     "012345678901234567890123456789012345678901234567890123456789"
2643     "012345678901234567890123456789012345678901234567890123456789"
2644     "012345678901234567890123456789012345678901234567890123456789"
2645     "012345678901234567890123456789012345678901234567890123456789"
2646     "012345678901234567890123456789012345678901234567890123456789"
2647     "012345678901234567890123456789012345678901234567890123456789"
2648     "012345678901234567890123456789012345678901234567890123456789"
2649     "012345678901234567890123456789012345678901234567890123456789"
2650     "]]></s>";
2651 
2652 /* Test stopping the parser in cdata handler */
START_TEST(test_stop_parser_between_cdata_calls)2653 START_TEST(test_stop_parser_between_cdata_calls)
2654 {
2655     const char *text = long_cdata_text;
2656 
2657     XML_SetCharacterDataHandler(parser,
2658                                 clearing_aborting_character_handler);
2659     resumable = XML_FALSE;
2660     expect_failure(text, XML_ERROR_ABORTED,
2661                    "Parse not aborted in CDATA handler");
2662 }
2663 END_TEST
2664 
2665 /* Test suspending the parser in cdata handler */
START_TEST(test_suspend_parser_between_cdata_calls)2666 START_TEST(test_suspend_parser_between_cdata_calls)
2667 {
2668     const char *text = long_cdata_text;
2669     enum XML_Status result;
2670 
2671     XML_SetCharacterDataHandler(parser,
2672                                 clearing_aborting_character_handler);
2673     resumable = XML_TRUE;
2674     result = _XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE);
2675     if (result != XML_STATUS_SUSPENDED) {
2676         if (result == XML_STATUS_ERROR)
2677             xml_failure(parser);
2678         fail("Parse not suspended in CDATA handler");
2679     }
2680     if (XML_GetErrorCode(parser) != XML_ERROR_NONE)
2681         xml_failure(parser);
2682 }
2683 END_TEST
2684 
2685 /* Test memory allocation functions */
START_TEST(test_memory_allocation)2686 START_TEST(test_memory_allocation)
2687 {
2688     char *buffer = (char *)XML_MemMalloc(parser, 256);
2689     char *p;
2690 
2691     if (buffer == NULL) {
2692         fail("Allocation failed");
2693     } else {
2694         /* Try writing to memory; some OSes try to cheat! */
2695         buffer[0] = 'T';
2696         buffer[1] = 'E';
2697         buffer[2] = 'S';
2698         buffer[3] = 'T';
2699         buffer[4] = '\0';
2700         if (strcmp(buffer, "TEST") != 0) {
2701             fail("Memory not writable");
2702         } else {
2703             p = (char *)XML_MemRealloc(parser, buffer, 512);
2704             if (p == NULL) {
2705                 fail("Reallocation failed");
2706             } else {
2707                 /* Write again, just to be sure */
2708                 buffer = p;
2709                 buffer[0] = 'V';
2710                 if (strcmp(buffer, "VEST") != 0) {
2711                     fail("Reallocated memory not writable");
2712                 }
2713             }
2714         }
2715         XML_MemFree(parser, buffer);
2716     }
2717 }
2718 END_TEST
2719 
2720 static void XMLCALL
record_default_handler(void * userData,const XML_Char * UNUSED_P (s),int UNUSED_P (len))2721 record_default_handler(void *userData,
2722                        const XML_Char *UNUSED_P(s),
2723                        int UNUSED_P(len))
2724 {
2725     CharData_AppendXMLChars((CharData *)userData, XCS("D"), 1);
2726 }
2727 
2728 static void XMLCALL
record_cdata_handler(void * userData,const XML_Char * UNUSED_P (s),int UNUSED_P (len))2729 record_cdata_handler(void *userData,
2730                      const XML_Char *UNUSED_P(s),
2731                      int UNUSED_P(len))
2732 {
2733     CharData_AppendXMLChars((CharData *)userData, XCS("C"), 1);
2734     XML_DefaultCurrent(parser);
2735 }
2736 
2737 static void XMLCALL
record_cdata_nodefault_handler(void * userData,const XML_Char * UNUSED_P (s),int UNUSED_P (len))2738 record_cdata_nodefault_handler(void *userData,
2739                      const XML_Char *UNUSED_P(s),
2740                      int UNUSED_P(len))
2741 {
2742     CharData_AppendXMLChars((CharData *)userData, XCS("c"), 1);
2743 }
2744 
2745 static void XMLCALL
record_skip_handler(void * userData,const XML_Char * UNUSED_P (entityName),int is_parameter_entity)2746 record_skip_handler(void *userData,
2747                     const XML_Char *UNUSED_P(entityName),
2748                     int is_parameter_entity)
2749 {
2750     CharData_AppendXMLChars((CharData *)userData,
2751                             is_parameter_entity ? XCS("E") : XCS("e"), 1);
2752 }
2753 
2754 /* Test XML_DefaultCurrent() passes handling on correctly */
START_TEST(test_default_current)2755 START_TEST(test_default_current)
2756 {
2757     const char *text = "<doc>hell]</doc>";
2758     const char *entity_text =
2759         "<!DOCTYPE doc [\n"
2760         "<!ENTITY entity '&#37;'>\n"
2761         "]>\n"
2762         "<doc>&entity;</doc>";
2763     CharData storage;
2764 
2765     XML_SetDefaultHandler(parser, record_default_handler);
2766     XML_SetCharacterDataHandler(parser, record_cdata_handler);
2767     CharData_Init(&storage);
2768     XML_SetUserData(parser, &storage);
2769     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
2770                                 XML_TRUE) == XML_STATUS_ERROR)
2771         xml_failure(parser);
2772     CharData_CheckXMLChars(&storage, XCS("DCDCDCDCDCDD"));
2773 
2774     /* Again, without the defaulting */
2775     XML_ParserReset(parser, NULL);
2776     XML_SetDefaultHandler(parser, record_default_handler);
2777     XML_SetCharacterDataHandler(parser, record_cdata_nodefault_handler);
2778     CharData_Init(&storage);
2779     XML_SetUserData(parser, &storage);
2780     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
2781                                 XML_TRUE) == XML_STATUS_ERROR)
2782         xml_failure(parser);
2783     CharData_CheckXMLChars(&storage, XCS("DcccccD"));
2784 
2785     /* Now with an internal entity to complicate matters */
2786     XML_ParserReset(parser, NULL);
2787     XML_SetDefaultHandler(parser, record_default_handler);
2788     XML_SetCharacterDataHandler(parser, record_cdata_handler);
2789     CharData_Init(&storage);
2790     XML_SetUserData(parser, &storage);
2791     if (_XML_Parse_SINGLE_BYTES(parser, entity_text, strlen(entity_text),
2792                                 XML_TRUE) == XML_STATUS_ERROR)
2793         xml_failure(parser);
2794     /* The default handler suppresses the entity */
2795     CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDDD"));
2796 
2797     /* Again, with a skip handler */
2798     XML_ParserReset(parser, NULL);
2799     XML_SetDefaultHandler(parser, record_default_handler);
2800     XML_SetCharacterDataHandler(parser, record_cdata_handler);
2801     XML_SetSkippedEntityHandler(parser, record_skip_handler);
2802     CharData_Init(&storage);
2803     XML_SetUserData(parser, &storage);
2804     if (_XML_Parse_SINGLE_BYTES(parser, entity_text, strlen(entity_text),
2805                                 XML_TRUE) == XML_STATUS_ERROR)
2806         xml_failure(parser);
2807     /* The default handler suppresses the entity */
2808     CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDeD"));
2809 
2810     /* This time, allow the entity through */
2811     XML_ParserReset(parser, NULL);
2812     XML_SetDefaultHandlerExpand(parser, record_default_handler);
2813     XML_SetCharacterDataHandler(parser, record_cdata_handler);
2814     CharData_Init(&storage);
2815     XML_SetUserData(parser, &storage);
2816     if (_XML_Parse_SINGLE_BYTES(parser, entity_text, strlen(entity_text),
2817                                 XML_TRUE) == XML_STATUS_ERROR)
2818         xml_failure(parser);
2819     CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDCDD"));
2820 
2821     /* Finally, without passing the cdata to the default handler */
2822     XML_ParserReset(parser, NULL);
2823     XML_SetDefaultHandlerExpand(parser, record_default_handler);
2824     XML_SetCharacterDataHandler(parser, record_cdata_nodefault_handler);
2825     CharData_Init(&storage);
2826     XML_SetUserData(parser, &storage);
2827     if (_XML_Parse_SINGLE_BYTES(parser, entity_text, strlen(entity_text),
2828                                 XML_TRUE) == XML_STATUS_ERROR)
2829         xml_failure(parser);
2830     CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDcD"));
2831 }
2832 END_TEST
2833 
2834 /* Test DTD element parsing code paths */
START_TEST(test_dtd_elements)2835 START_TEST(test_dtd_elements)
2836 {
2837     const char *text =
2838         "<!DOCTYPE doc [\n"
2839         "<!ELEMENT doc (chapter)>\n"
2840         "<!ELEMENT chapter (#PCDATA)>\n"
2841         "]>\n"
2842         "<doc><chapter>Wombats are go</chapter></doc>";
2843 
2844     XML_SetElementDeclHandler(parser, dummy_element_decl_handler);
2845     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
2846                                 XML_TRUE) == XML_STATUS_ERROR)
2847         xml_failure(parser);
2848 }
2849 END_TEST
2850 
2851 /* Test foreign DTD handling */
START_TEST(test_set_foreign_dtd)2852 START_TEST(test_set_foreign_dtd)
2853 {
2854     const char *text1 =
2855         "<?xml version='1.0' encoding='us-ascii'?>\n";
2856     const char *text2 =
2857         "<doc>&entity;</doc>";
2858     ExtTest test_data = {
2859         "<!ELEMENT doc (#PCDATA)*>",
2860         NULL,
2861         NULL
2862     };
2863 
2864     /* Check hash salt is passed through too */
2865     XML_SetHashSalt(parser, 0x12345678);
2866     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2867     XML_SetUserData(parser, &test_data);
2868     XML_SetExternalEntityRefHandler(parser, external_entity_loader);
2869     /* Add a default handler to exercise more code paths */
2870     XML_SetDefaultHandler(parser, dummy_default_handler);
2871     if (XML_UseForeignDTD(parser, XML_TRUE) != XML_ERROR_NONE)
2872         fail("Could not set foreign DTD");
2873     if (_XML_Parse_SINGLE_BYTES(parser, text1, strlen(text1),
2874                                 XML_FALSE) == XML_STATUS_ERROR)
2875         xml_failure(parser);
2876 
2877     /* Ensure that trying to set the DTD after parsing has started
2878      * is faulted, even if it's the same setting.
2879      */
2880     if (XML_UseForeignDTD(parser, XML_TRUE) !=
2881         XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING)
2882         fail("Failed to reject late foreign DTD setting");
2883     /* Ditto for the hash salt */
2884     if (XML_SetHashSalt(parser, 0x23456789))
2885         fail("Failed to reject late hash salt change");
2886 
2887     /* Now finish the parse */
2888     if (_XML_Parse_SINGLE_BYTES(parser, text2, strlen(text2),
2889                                 XML_TRUE) == XML_STATUS_ERROR)
2890         xml_failure(parser);
2891 }
2892 END_TEST
2893 
2894 /* Test foreign DTD handling with a failing NotStandalone handler */
START_TEST(test_foreign_dtd_not_standalone)2895 START_TEST(test_foreign_dtd_not_standalone)
2896 {
2897     const char *text =
2898         "<?xml version='1.0' encoding='us-ascii'?>\n"
2899         "<doc>&entity;</doc>";
2900     ExtTest test_data = {
2901         "<!ELEMENT doc (#PCDATA)*>",
2902         NULL,
2903         NULL
2904     };
2905 
2906     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2907     XML_SetUserData(parser, &test_data);
2908     XML_SetExternalEntityRefHandler(parser, external_entity_loader);
2909     XML_SetNotStandaloneHandler(parser, reject_not_standalone_handler);
2910     if (XML_UseForeignDTD(parser, XML_TRUE) != XML_ERROR_NONE)
2911         fail("Could not set foreign DTD");
2912     expect_failure(text, XML_ERROR_NOT_STANDALONE,
2913                    "NotStandalonehandler failed to reject");
2914 }
2915 END_TEST
2916 
2917 /* Test invalid character in a foreign DTD is faulted */
START_TEST(test_invalid_foreign_dtd)2918 START_TEST(test_invalid_foreign_dtd)
2919 {
2920     const char *text =
2921         "<?xml version='1.0' encoding='us-ascii'?>\n"
2922         "<doc>&entity;</doc>";
2923     ExtFaults test_data = {
2924         "$",
2925         "Dollar not faulted",
2926         NULL,
2927         XML_ERROR_INVALID_TOKEN
2928     };
2929 
2930     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2931     XML_SetUserData(parser, &test_data);
2932     XML_SetExternalEntityRefHandler(parser, external_entity_faulter);
2933     XML_UseForeignDTD(parser, XML_TRUE);
2934     expect_failure(text,
2935                    XML_ERROR_EXTERNAL_ENTITY_HANDLING,
2936                    "Bad DTD should not have been accepted");
2937 }
2938 END_TEST
2939 
2940 /* Test foreign DTD use with a doctype */
START_TEST(test_foreign_dtd_with_doctype)2941 START_TEST(test_foreign_dtd_with_doctype)
2942 {
2943     const char *text1 =
2944         "<?xml version='1.0' encoding='us-ascii'?>\n"
2945         "<!DOCTYPE doc [<!ENTITY entity 'hello world'>]>\n";
2946     const char *text2 =
2947         "<doc>&entity;</doc>";
2948     ExtTest test_data = {
2949         "<!ELEMENT doc (#PCDATA)*>",
2950         NULL,
2951         NULL
2952     };
2953 
2954     /* Check hash salt is passed through too */
2955     XML_SetHashSalt(parser, 0x12345678);
2956     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2957     XML_SetUserData(parser, &test_data);
2958     XML_SetExternalEntityRefHandler(parser, external_entity_loader);
2959     /* Add a default handler to exercise more code paths */
2960     XML_SetDefaultHandler(parser, dummy_default_handler);
2961     if (XML_UseForeignDTD(parser, XML_TRUE) != XML_ERROR_NONE)
2962         fail("Could not set foreign DTD");
2963     if (_XML_Parse_SINGLE_BYTES(parser, text1, strlen(text1),
2964                                 XML_FALSE) == XML_STATUS_ERROR)
2965         xml_failure(parser);
2966 
2967     /* Ensure that trying to set the DTD after parsing has started
2968      * is faulted, even if it's the same setting.
2969      */
2970     if (XML_UseForeignDTD(parser, XML_TRUE) !=
2971         XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING)
2972         fail("Failed to reject late foreign DTD setting");
2973     /* Ditto for the hash salt */
2974     if (XML_SetHashSalt(parser, 0x23456789))
2975         fail("Failed to reject late hash salt change");
2976 
2977     /* Now finish the parse */
2978     if (_XML_Parse_SINGLE_BYTES(parser, text2, strlen(text2),
2979                                 XML_TRUE) == XML_STATUS_ERROR)
2980         xml_failure(parser);
2981 }
2982 END_TEST
2983 
2984 /* Test XML_UseForeignDTD with no external subset present */
2985 static int XMLCALL
external_entity_null_loader(XML_Parser UNUSED_P (parser),const XML_Char * UNUSED_P (context),const XML_Char * UNUSED_P (base),const XML_Char * UNUSED_P (systemId),const XML_Char * UNUSED_P (publicId))2986 external_entity_null_loader(XML_Parser UNUSED_P(parser),
2987                             const XML_Char *UNUSED_P(context),
2988                             const XML_Char *UNUSED_P(base),
2989                             const XML_Char *UNUSED_P(systemId),
2990                             const XML_Char *UNUSED_P(publicId))
2991 {
2992     return XML_STATUS_OK;
2993 }
2994 
START_TEST(test_foreign_dtd_without_external_subset)2995 START_TEST(test_foreign_dtd_without_external_subset)
2996 {
2997     const char *text =
2998         "<!DOCTYPE doc [<!ENTITY foo 'bar'>]>\n"
2999         "<doc>&foo;</doc>";
3000 
3001     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3002     XML_SetUserData(parser, NULL);
3003     XML_SetExternalEntityRefHandler(parser, external_entity_null_loader);
3004     XML_UseForeignDTD(parser, XML_TRUE);
3005     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
3006                                 XML_TRUE) == XML_STATUS_ERROR)
3007         xml_failure(parser);
3008 }
3009 END_TEST
3010 
START_TEST(test_empty_foreign_dtd)3011 START_TEST(test_empty_foreign_dtd)
3012 {
3013     const char *text =
3014         "<?xml version='1.0' encoding='us-ascii'?>\n"
3015         "<doc>&entity;</doc>";
3016 
3017     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3018     XML_SetExternalEntityRefHandler(parser, external_entity_null_loader);
3019     XML_UseForeignDTD(parser, XML_TRUE);
3020     expect_failure(text, XML_ERROR_UNDEFINED_ENTITY,
3021                    "Undefined entity not faulted");
3022 }
3023 END_TEST
3024 
3025 /* Test XML Base is set and unset appropriately */
START_TEST(test_set_base)3026 START_TEST(test_set_base)
3027 {
3028     const XML_Char *old_base;
3029     const XML_Char *new_base = XCS("/local/file/name.xml");
3030 
3031     old_base = XML_GetBase(parser);
3032     if (XML_SetBase(parser, new_base) != XML_STATUS_OK)
3033         fail("Unable to set base");
3034     if (xcstrcmp(XML_GetBase(parser), new_base) != 0)
3035         fail("Base setting not correct");
3036     if (XML_SetBase(parser, NULL) != XML_STATUS_OK)
3037         fail("Unable to NULL base");
3038     if (XML_GetBase(parser) != NULL)
3039         fail("Base setting not nulled");
3040     XML_SetBase(parser, old_base);
3041 }
3042 END_TEST
3043 
3044 /* Test attribute counts, indexing, etc */
3045 typedef struct attrInfo {
3046     const XML_Char *name;
3047     const XML_Char *value;
3048 } AttrInfo;
3049 
3050 typedef struct elementInfo {
3051     const XML_Char *name;
3052     int attr_count;
3053     const XML_Char *id_name;
3054     AttrInfo *attributes;
3055 } ElementInfo;
3056 
3057 static void XMLCALL
counting_start_element_handler(void * userData,const XML_Char * name,const XML_Char ** atts)3058 counting_start_element_handler(void *userData,
3059                                const XML_Char *name,
3060                                const XML_Char **atts)
3061 {
3062     ElementInfo *info = (ElementInfo *)userData;
3063     AttrInfo *attr;
3064     int count, id, i;
3065 
3066     while (info->name != NULL) {
3067         if (!xcstrcmp(name, info->name))
3068             break;
3069         info++;
3070     }
3071     if (info->name == NULL)
3072         fail("Element not recognised");
3073     /* The attribute count is twice what you might expect.  It is a
3074      * count of items in atts, an array which contains alternating
3075      * attribute names and attribute values.  For the naive user this
3076      * is possibly a little unexpected, but it is what the
3077      * documentation in expat.h tells us to expect.
3078      */
3079     count = XML_GetSpecifiedAttributeCount(parser);
3080     if (info->attr_count * 2 != count) {
3081         fail("Not got expected attribute count");
3082         return;
3083     }
3084     id = XML_GetIdAttributeIndex(parser);
3085     if (id == -1 && info->id_name != NULL) {
3086         fail("ID not present");
3087         return;
3088     }
3089     if (id != -1 && xcstrcmp(atts[id], info->id_name)) {
3090         fail("ID does not have the correct name");
3091         return;
3092     }
3093     for (i = 0; i < info->attr_count; i++) {
3094         attr = info->attributes;
3095         while (attr->name != NULL) {
3096             if (!xcstrcmp(atts[0], attr->name))
3097                 break;
3098             attr++;
3099         }
3100         if (attr->name == NULL) {
3101             fail("Attribute not recognised");
3102             return;
3103         }
3104         if (xcstrcmp(atts[1], attr->value)) {
3105             fail("Attribute has wrong value");
3106             return;
3107         }
3108         /* Remember, two entries in atts per attribute (see above) */
3109         atts += 2;
3110     }
3111 }
3112 
START_TEST(test_attributes)3113 START_TEST(test_attributes)
3114 {
3115     const char *text =
3116         "<!DOCTYPE doc [\n"
3117         "<!ELEMENT doc (tag)>\n"
3118         "<!ATTLIST doc id ID #REQUIRED>\n"
3119         "]>"
3120         "<doc a='1' id='one' b='2'>"
3121         "<tag c='3'/>"
3122         "</doc>";
3123     AttrInfo doc_info[] = {
3124         { XCS("a"),  XCS("1") },
3125         { XCS("b"),  XCS("2") },
3126         { XCS("id"), XCS("one") },
3127         { NULL, NULL }
3128     };
3129     AttrInfo tag_info[] = {
3130         { XCS("c"),  XCS("3") },
3131         { NULL, NULL }
3132     };
3133     ElementInfo info[] = {
3134         { XCS("doc"), 3, XCS("id"), NULL },
3135         { XCS("tag"), 1, NULL, NULL },
3136         { NULL, 0, NULL, NULL }
3137     };
3138     info[0].attributes = doc_info;
3139     info[1].attributes = tag_info;
3140 
3141     XML_SetStartElementHandler(parser, counting_start_element_handler);
3142     XML_SetUserData(parser, info);
3143     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
3144         xml_failure(parser);
3145 }
3146 END_TEST
3147 
3148 /* Test reset works correctly in the middle of processing an internal
3149  * entity.  Exercises some obscure code in XML_ParserReset().
3150  */
START_TEST(test_reset_in_entity)3151 START_TEST(test_reset_in_entity)
3152 {
3153     const char *text =
3154         "<!DOCTYPE doc [\n"
3155         "<!ENTITY wombat 'wom'>\n"
3156         "<!ENTITY entity 'hi &wom; there'>\n"
3157         "]>\n"
3158         "<doc>&entity;</doc>";
3159     XML_ParsingStatus status;
3160 
3161     resumable = XML_TRUE;
3162     XML_SetCharacterDataHandler(parser, clearing_aborting_character_handler);
3163     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_FALSE) == XML_STATUS_ERROR)
3164         xml_failure(parser);
3165     XML_GetParsingStatus(parser, &status);
3166     if (status.parsing != XML_SUSPENDED)
3167         fail("Parsing status not SUSPENDED");
3168     XML_ParserReset(parser, NULL);
3169     XML_GetParsingStatus(parser, &status);
3170     if (status.parsing != XML_INITIALIZED)
3171         fail("Parsing status doesn't reset to INITIALIZED");
3172 }
3173 END_TEST
3174 
3175 /* Test that resume correctly passes through parse errors */
START_TEST(test_resume_invalid_parse)3176 START_TEST(test_resume_invalid_parse)
3177 {
3178     const char *text = "<doc>Hello</doc"; /* Missing closing wedge */
3179 
3180     resumable = XML_TRUE;
3181     XML_SetCharacterDataHandler(parser,
3182                                 clearing_aborting_character_handler);
3183     if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
3184         xml_failure(parser);
3185     if (XML_ResumeParser(parser) == XML_STATUS_OK)
3186         fail("Resumed invalid parse not faulted");
3187     if (XML_GetErrorCode(parser) != XML_ERROR_UNCLOSED_TOKEN)
3188         fail("Invalid parse not correctly faulted");
3189 }
3190 END_TEST
3191 
3192 /* Test that re-suspended parses are correctly passed through */
START_TEST(test_resume_resuspended)3193 START_TEST(test_resume_resuspended)
3194 {
3195     const char *text = "<doc>Hello<meep/>world</doc>";
3196 
3197     resumable = XML_TRUE;
3198     XML_SetCharacterDataHandler(parser,
3199                                 clearing_aborting_character_handler);
3200     if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
3201         xml_failure(parser);
3202     resumable = XML_TRUE;
3203     XML_SetCharacterDataHandler(parser,
3204                                 clearing_aborting_character_handler);
3205     if (XML_ResumeParser(parser) != XML_STATUS_SUSPENDED)
3206         fail("Resumption not suspended");
3207     /* This one should succeed and finish up */
3208     if (XML_ResumeParser(parser) != XML_STATUS_OK)
3209         xml_failure(parser);
3210 }
3211 END_TEST
3212 
3213 /* Test that CDATA shows up correctly through a default handler */
START_TEST(test_cdata_default)3214 START_TEST(test_cdata_default)
3215 {
3216     const char *text = "<doc><![CDATA[Hello\nworld]]></doc>";
3217     const XML_Char *expected = XCS("<doc><![CDATA[Hello\nworld]]></doc>");
3218     CharData storage;
3219 
3220     CharData_Init(&storage);
3221     XML_SetUserData(parser, &storage);
3222     XML_SetDefaultHandler(parser, accumulate_characters);
3223 
3224     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
3225                                 XML_TRUE) == XML_STATUS_ERROR)
3226         xml_failure(parser);
3227     CharData_CheckXMLChars(&storage, expected);
3228 }
3229 END_TEST
3230 
3231 /* Test resetting a subordinate parser does exactly nothing */
3232 static int XMLCALL
external_entity_resetter(XML_Parser parser,const XML_Char * context,const XML_Char * UNUSED_P (base),const XML_Char * UNUSED_P (systemId),const XML_Char * UNUSED_P (publicId))3233 external_entity_resetter(XML_Parser parser,
3234                          const XML_Char *context,
3235                          const XML_Char *UNUSED_P(base),
3236                          const XML_Char *UNUSED_P(systemId),
3237                          const XML_Char *UNUSED_P(publicId))
3238 {
3239     const char *text = "<!ELEMENT doc (#PCDATA)*>";
3240     XML_Parser ext_parser;
3241     XML_ParsingStatus status;
3242 
3243     ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3244     if (ext_parser == NULL)
3245         fail("Could not create external entity parser");
3246     XML_GetParsingStatus(ext_parser, &status);
3247     if (status.parsing != XML_INITIALIZED) {
3248         fail("Parsing status is not INITIALIZED");
3249         return XML_STATUS_ERROR;
3250     }
3251     if (_XML_Parse_SINGLE_BYTES(ext_parser, text, strlen(text),
3252                                 XML_TRUE) == XML_STATUS_ERROR) {
3253         xml_failure(parser);
3254         return XML_STATUS_ERROR;
3255     }
3256     XML_GetParsingStatus(ext_parser, &status);
3257     if (status.parsing != XML_FINISHED) {
3258         fail("Parsing status is not FINISHED");
3259         return XML_STATUS_ERROR;
3260     }
3261     /* Check we can't parse here */
3262     if (XML_Parse(ext_parser, text, strlen(text),
3263                   XML_TRUE) != XML_STATUS_ERROR)
3264         fail("Parsing when finished not faulted");
3265     if (XML_GetErrorCode(ext_parser) != XML_ERROR_FINISHED)
3266         fail("Parsing when finished faulted with wrong code");
3267     XML_ParserReset(ext_parser, NULL);
3268     XML_GetParsingStatus(ext_parser, &status);
3269     if (status.parsing != XML_FINISHED) {
3270         fail("Parsing status not still FINISHED");
3271         return XML_STATUS_ERROR;
3272     }
3273     XML_ParserFree(ext_parser);
3274     return XML_STATUS_OK;
3275 }
3276 
START_TEST(test_subordinate_reset)3277 START_TEST(test_subordinate_reset)
3278 {
3279     const char *text =
3280         "<?xml version='1.0' encoding='us-ascii'?>\n"
3281         "<!DOCTYPE doc SYSTEM 'foo'>\n"
3282         "<doc>&entity;</doc>";
3283 
3284     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3285     XML_SetExternalEntityRefHandler(parser, external_entity_resetter);
3286     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
3287         xml_failure(parser);
3288 }
3289 END_TEST
3290 
3291 
3292 /* Test suspending a subordinate parser */
3293 
3294 static void XMLCALL
entity_suspending_decl_handler(void * userData,const XML_Char * UNUSED_P (name),XML_Content * model)3295 entity_suspending_decl_handler(void *userData,
3296                                const XML_Char *UNUSED_P(name),
3297                                XML_Content *model)
3298 {
3299     XML_Parser ext_parser = (XML_Parser)userData;
3300 
3301     if (XML_StopParser(ext_parser, XML_TRUE) != XML_STATUS_ERROR)
3302         fail("Attempting to suspend a subordinate parser not faulted");
3303     if (XML_GetErrorCode(ext_parser) != XML_ERROR_SUSPEND_PE)
3304         fail("Suspending subordinate parser get wrong code");
3305     XML_SetElementDeclHandler(ext_parser, NULL);
3306     XML_FreeContentModel(parser, model);
3307 }
3308 
3309 static int XMLCALL
external_entity_suspender(XML_Parser parser,const XML_Char * context,const XML_Char * UNUSED_P (base),const XML_Char * UNUSED_P (systemId),const XML_Char * UNUSED_P (publicId))3310 external_entity_suspender(XML_Parser parser,
3311                           const XML_Char *context,
3312                           const XML_Char *UNUSED_P(base),
3313                           const XML_Char *UNUSED_P(systemId),
3314                           const XML_Char *UNUSED_P(publicId))
3315 {
3316     const char *text = "<!ELEMENT doc (#PCDATA)*>";
3317     XML_Parser ext_parser;
3318 
3319     ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3320     if (ext_parser == NULL)
3321         fail("Could not create external entity parser");
3322     XML_SetElementDeclHandler(ext_parser, entity_suspending_decl_handler);
3323     XML_SetUserData(ext_parser, ext_parser);
3324     if (_XML_Parse_SINGLE_BYTES(ext_parser, text, strlen(text),
3325                                 XML_TRUE) == XML_STATUS_ERROR) {
3326         xml_failure(ext_parser);
3327         return XML_STATUS_ERROR;
3328     }
3329     XML_ParserFree(ext_parser);
3330     return XML_STATUS_OK;
3331 }
3332 
START_TEST(test_subordinate_suspend)3333 START_TEST(test_subordinate_suspend)
3334 {
3335     const char *text =
3336         "<?xml version='1.0' encoding='us-ascii'?>\n"
3337         "<!DOCTYPE doc SYSTEM 'foo'>\n"
3338         "<doc>&entity;</doc>";
3339 
3340     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3341     XML_SetExternalEntityRefHandler(parser, external_entity_suspender);
3342     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
3343         xml_failure(parser);
3344 }
3345 END_TEST
3346 
3347 /* Test suspending a subordinate parser from an XML declaration */
3348 /* Increases code coverage of the tests */
3349 static void XMLCALL
entity_suspending_xdecl_handler(void * userData,const XML_Char * UNUSED_P (version),const XML_Char * UNUSED_P (encoding),int UNUSED_P (standalone))3350 entity_suspending_xdecl_handler(void *userData,
3351                                 const XML_Char *UNUSED_P(version),
3352                                 const XML_Char *UNUSED_P(encoding),
3353                                 int UNUSED_P(standalone))
3354 {
3355     XML_Parser ext_parser = (XML_Parser)userData;
3356 
3357     XML_StopParser(ext_parser, resumable);
3358     XML_SetXmlDeclHandler(ext_parser, NULL);
3359 }
3360 
3361 static int XMLCALL
external_entity_suspend_xmldecl(XML_Parser parser,const XML_Char * context,const XML_Char * UNUSED_P (base),const XML_Char * UNUSED_P (systemId),const XML_Char * UNUSED_P (publicId))3362 external_entity_suspend_xmldecl(XML_Parser parser,
3363                                 const XML_Char *context,
3364                                 const XML_Char *UNUSED_P(base),
3365                                 const XML_Char *UNUSED_P(systemId),
3366                                 const XML_Char *UNUSED_P(publicId))
3367 {
3368     const char *text = "<?xml version='1.0' encoding='us-ascii'?>";
3369     XML_Parser ext_parser;
3370     XML_ParsingStatus status;
3371     enum XML_Status rc;
3372 
3373     ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3374     if (ext_parser == NULL)
3375         fail("Could not create external entity parser");
3376     XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
3377     XML_SetUserData(ext_parser, ext_parser);
3378     rc = _XML_Parse_SINGLE_BYTES(ext_parser, text, strlen(text), XML_TRUE);
3379     XML_GetParsingStatus(ext_parser, &status);
3380     if (resumable) {
3381         if (rc == XML_STATUS_ERROR)
3382             xml_failure(ext_parser);
3383         if (status.parsing != XML_SUSPENDED)
3384             fail("Ext Parsing status not SUSPENDED");
3385     } else {
3386         if (rc != XML_STATUS_ERROR)
3387             fail("Ext parsing not aborted");
3388         if (XML_GetErrorCode(ext_parser) != XML_ERROR_ABORTED)
3389             xml_failure(ext_parser);
3390         if (status.parsing != XML_FINISHED)
3391             fail("Ext Parsing status not FINISHED");
3392     }
3393 
3394     XML_ParserFree(ext_parser);
3395     return XML_STATUS_OK;
3396 }
3397 
START_TEST(test_subordinate_xdecl_suspend)3398 START_TEST(test_subordinate_xdecl_suspend)
3399 {
3400     const char *text =
3401         "<!DOCTYPE doc [\n"
3402         "  <!ENTITY entity SYSTEM 'http://example.org/dummy.ent'>\n"
3403         "]>\n"
3404         "<doc>&entity;</doc>";
3405 
3406     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3407     XML_SetExternalEntityRefHandler(parser,
3408                                     external_entity_suspend_xmldecl);
3409     resumable = XML_TRUE;
3410     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
3411                                 XML_TRUE) == XML_STATUS_ERROR)
3412         xml_failure(parser);
3413 }
3414 END_TEST
3415 
START_TEST(test_subordinate_xdecl_abort)3416 START_TEST(test_subordinate_xdecl_abort)
3417 {
3418     const char *text =
3419         "<!DOCTYPE doc [\n"
3420         "  <!ENTITY entity SYSTEM 'http://example.org/dummy.ent'>\n"
3421         "]>\n"
3422         "<doc>&entity;</doc>";
3423 
3424     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3425     XML_SetExternalEntityRefHandler(parser,
3426                                     external_entity_suspend_xmldecl);
3427     resumable = XML_FALSE;
3428     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
3429                                 XML_TRUE) == XML_STATUS_ERROR)
3430         xml_failure(parser);
3431 }
3432 END_TEST
3433 
3434 /* Test external entity fault handling with suspension */
3435 static int XMLCALL
external_entity_suspending_faulter(XML_Parser parser,const XML_Char * context,const XML_Char * UNUSED_P (base),const XML_Char * UNUSED_P (systemId),const XML_Char * UNUSED_P (publicId))3436 external_entity_suspending_faulter(XML_Parser parser,
3437                                    const XML_Char *context,
3438                                    const XML_Char *UNUSED_P(base),
3439                                    const XML_Char *UNUSED_P(systemId),
3440                                    const XML_Char *UNUSED_P(publicId))
3441 {
3442     XML_Parser ext_parser;
3443     ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser);
3444     void *buffer;
3445     int parse_len = strlen(fault->parse_text);
3446 
3447     ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3448     if (ext_parser == NULL)
3449         fail("Could not create external entity parser");
3450     XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
3451     XML_SetUserData(ext_parser, ext_parser);
3452     resumable = XML_TRUE;
3453     buffer = XML_GetBuffer(ext_parser, parse_len);
3454     if (buffer == NULL)
3455         fail("Could not allocate parse buffer");
3456     memcpy(buffer, fault->parse_text, parse_len);
3457     if (XML_ParseBuffer(ext_parser, parse_len,
3458                         XML_FALSE) != XML_STATUS_SUSPENDED)
3459         fail("XML declaration did not suspend");
3460     if (XML_ResumeParser(ext_parser) != XML_STATUS_OK)
3461         xml_failure(ext_parser);
3462     if (XML_ParseBuffer(ext_parser, 0, XML_TRUE) != XML_STATUS_ERROR)
3463         fail(fault->fail_text);
3464     if (XML_GetErrorCode(ext_parser) != fault->error)
3465         xml_failure(ext_parser);
3466 
3467     XML_ParserFree(ext_parser);
3468     return XML_STATUS_ERROR;
3469 }
3470 
START_TEST(test_ext_entity_invalid_suspended_parse)3471 START_TEST(test_ext_entity_invalid_suspended_parse)
3472 {
3473     const char *text =
3474         "<!DOCTYPE doc [\n"
3475         "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
3476         "]>\n"
3477         "<doc>&en;</doc>";
3478     ExtFaults faults[] = {
3479         {
3480             "<?xml version='1.0' encoding='us-ascii'?><",
3481             "Incomplete element declaration not faulted",
3482             NULL,
3483             XML_ERROR_UNCLOSED_TOKEN
3484         },
3485         {
3486             /* First two bytes of a three-byte char */
3487             "<?xml version='1.0' encoding='utf-8'?>\xe2\x82",
3488             "Incomplete character not faulted",
3489             NULL,
3490             XML_ERROR_PARTIAL_CHAR
3491         },
3492         { NULL, NULL, NULL, XML_ERROR_NONE }
3493     };
3494     ExtFaults *fault;
3495 
3496     for (fault = &faults[0]; fault->parse_text != NULL; fault++) {
3497         XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3498         XML_SetExternalEntityRefHandler(parser,
3499                                         external_entity_suspending_faulter);
3500         XML_SetUserData(parser, fault);
3501         expect_failure(text,
3502                        XML_ERROR_EXTERNAL_ENTITY_HANDLING,
3503                        "Parser did not report external entity error");
3504         XML_ParserReset(parser, NULL);
3505     }
3506 }
3507 END_TEST
3508 
3509 
3510 
3511 /* Test setting an explicit encoding */
START_TEST(test_explicit_encoding)3512 START_TEST(test_explicit_encoding)
3513 {
3514     const char *text1 = "<doc>Hello ";
3515     const char *text2 = " World</doc>";
3516 
3517     /* Just check that we can set the encoding to NULL before starting */
3518     if (XML_SetEncoding(parser, NULL) != XML_STATUS_OK)
3519         fail("Failed to initialise encoding to NULL");
3520     /* Say we are UTF-8 */
3521     if (XML_SetEncoding(parser, XCS("utf-8")) != XML_STATUS_OK)
3522         fail("Failed to set explicit encoding");
3523     if (_XML_Parse_SINGLE_BYTES(parser, text1, strlen(text1),
3524                                 XML_FALSE) == XML_STATUS_ERROR)
3525         xml_failure(parser);
3526     /* Try to switch encodings mid-parse */
3527     if (XML_SetEncoding(parser, XCS("us-ascii")) != XML_STATUS_ERROR)
3528         fail("Allowed encoding change");
3529     if (_XML_Parse_SINGLE_BYTES(parser, text2, strlen(text2),
3530                                 XML_TRUE) == XML_STATUS_ERROR)
3531         xml_failure(parser);
3532     /* Try now the parse is over */
3533     if (XML_SetEncoding(parser, NULL) != XML_STATUS_OK)
3534         fail("Failed to unset encoding");
3535 }
3536 END_TEST
3537 
3538 
3539 /* Test handling of trailing CR (rather than newline) */
3540 static void XMLCALL
cr_cdata_handler(void * userData,const XML_Char * s,int len)3541 cr_cdata_handler(void *userData, const XML_Char *s, int len)
3542 {
3543     int *pfound = (int *)userData;
3544 
3545     /* Internal processing turns the CR into a newline for the
3546      * character data handler, but not for the default handler
3547      */
3548     if (len == 1 && (*s == XCS('\n') || *s == XCS('\r')))
3549         *pfound = 1;
3550 }
3551 
START_TEST(test_trailing_cr)3552 START_TEST(test_trailing_cr)
3553 {
3554     const char *text = "<doc>\r";
3555     int found_cr;
3556 
3557     /* Try with a character handler, for code coverage */
3558     XML_SetCharacterDataHandler(parser, cr_cdata_handler);
3559     XML_SetUserData(parser, &found_cr);
3560     found_cr = 0;
3561     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
3562                                 XML_TRUE) == XML_STATUS_OK)
3563         fail("Failed to fault unclosed doc");
3564     if (found_cr == 0)
3565         fail("Did not catch the carriage return");
3566     XML_ParserReset(parser, NULL);
3567 
3568     /* Now with a default handler instead */
3569     XML_SetDefaultHandler(parser, cr_cdata_handler);
3570     XML_SetUserData(parser, &found_cr);
3571     found_cr = 0;
3572     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
3573                                 XML_TRUE) == XML_STATUS_OK)
3574         fail("Failed to fault unclosed doc");
3575     if (found_cr == 0)
3576         fail("Did not catch default carriage return");
3577 }
3578 END_TEST
3579 
3580 /* Test trailing CR in an external entity parse */
3581 static int XMLCALL
external_entity_cr_catcher(XML_Parser parser,const XML_Char * context,const XML_Char * UNUSED_P (base),const XML_Char * UNUSED_P (systemId),const XML_Char * UNUSED_P (publicId))3582 external_entity_cr_catcher(XML_Parser parser,
3583                            const XML_Char *context,
3584                            const XML_Char *UNUSED_P(base),
3585                            const XML_Char *UNUSED_P(systemId),
3586                            const XML_Char *UNUSED_P(publicId))
3587 {
3588     const char *text = "\r";
3589     XML_Parser ext_parser;
3590 
3591     ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3592     if (ext_parser == NULL)
3593         fail("Could not create external entity parser");
3594     XML_SetCharacterDataHandler(ext_parser, cr_cdata_handler);
3595     if (_XML_Parse_SINGLE_BYTES(ext_parser, text, strlen(text),
3596                                 XML_TRUE) == XML_STATUS_ERROR)
3597         xml_failure(ext_parser);
3598     XML_ParserFree(ext_parser);
3599     return XML_STATUS_OK;
3600 }
3601 
3602 static int XMLCALL
external_entity_bad_cr_catcher(XML_Parser parser,const XML_Char * context,const XML_Char * UNUSED_P (base),const XML_Char * UNUSED_P (systemId),const XML_Char * UNUSED_P (publicId))3603 external_entity_bad_cr_catcher(XML_Parser parser,
3604                                const XML_Char *context,
3605                                const XML_Char *UNUSED_P(base),
3606                                const XML_Char *UNUSED_P(systemId),
3607                                const XML_Char *UNUSED_P(publicId))
3608 {
3609     const char *text = "<tag>\r";
3610     XML_Parser ext_parser;
3611 
3612     ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3613     if (ext_parser == NULL)
3614         fail("Could not create external entity parser");
3615     XML_SetCharacterDataHandler(ext_parser, cr_cdata_handler);
3616     if (_XML_Parse_SINGLE_BYTES(ext_parser, text, strlen(text),
3617                                 XML_TRUE) == XML_STATUS_OK)
3618         fail("Async entity error not caught");
3619     if (XML_GetErrorCode(ext_parser) != XML_ERROR_ASYNC_ENTITY)
3620         xml_failure(ext_parser);
3621     XML_ParserFree(ext_parser);
3622     return XML_STATUS_OK;
3623 }
3624 
START_TEST(test_ext_entity_trailing_cr)3625 START_TEST(test_ext_entity_trailing_cr)
3626 {
3627     const char *text =
3628         "<!DOCTYPE doc [\n"
3629         "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
3630         "]>\n"
3631         "<doc>&en;</doc>";
3632     int found_cr;
3633 
3634     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3635     XML_SetExternalEntityRefHandler(parser, external_entity_cr_catcher);
3636     XML_SetUserData(parser, &found_cr);
3637     found_cr = 0;
3638     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
3639                                 XML_TRUE) != XML_STATUS_OK)
3640         xml_failure(parser);
3641     if (found_cr == 0)
3642         fail("No carriage return found");
3643     XML_ParserReset(parser, NULL);
3644 
3645     /* Try again with a different trailing CR */
3646     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3647     XML_SetExternalEntityRefHandler(parser, external_entity_bad_cr_catcher);
3648     XML_SetUserData(parser, &found_cr);
3649     found_cr = 0;
3650     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
3651                                 XML_TRUE) != XML_STATUS_OK)
3652         xml_failure(parser);
3653     if (found_cr == 0)
3654         fail("No carriage return found");
3655 }
3656 END_TEST
3657 
3658 /* Test handling of trailing square bracket */
3659 static void XMLCALL
rsqb_handler(void * userData,const XML_Char * s,int len)3660 rsqb_handler(void *userData, const XML_Char *s, int len)
3661 {
3662     int *pfound = (int *)userData;
3663 
3664     if (len == 1 && *s == XCS(']'))
3665         *pfound = 1;
3666 }
3667 
START_TEST(test_trailing_rsqb)3668 START_TEST(test_trailing_rsqb)
3669 {
3670     const char *text8 = "<doc>]";
3671     const char text16[] = "\xFF\xFE<\000d\000o\000c\000>\000]\000";
3672     int found_rsqb;
3673     int text8_len = strlen(text8);
3674 
3675     XML_SetCharacterDataHandler(parser, rsqb_handler);
3676     XML_SetUserData(parser, &found_rsqb);
3677     found_rsqb = 0;
3678     if (_XML_Parse_SINGLE_BYTES(parser, text8, text8_len,
3679                                 XML_TRUE) == XML_STATUS_OK)
3680         fail("Failed to fault unclosed doc");
3681     if (found_rsqb == 0)
3682         fail("Did not catch the right square bracket");
3683 
3684     /* Try again with a different encoding */
3685     XML_ParserReset(parser, NULL);
3686     XML_SetCharacterDataHandler(parser, rsqb_handler);
3687     XML_SetUserData(parser, &found_rsqb);
3688     found_rsqb = 0;
3689     if (_XML_Parse_SINGLE_BYTES(parser, text16, sizeof(text16)-1,
3690                                 XML_TRUE) == XML_STATUS_OK)
3691         fail("Failed to fault unclosed doc");
3692     if (found_rsqb == 0)
3693         fail("Did not catch the right square bracket");
3694 
3695     /* And finally with a default handler */
3696     XML_ParserReset(parser, NULL);
3697     XML_SetDefaultHandler(parser, rsqb_handler);
3698     XML_SetUserData(parser, &found_rsqb);
3699     found_rsqb = 0;
3700     if (_XML_Parse_SINGLE_BYTES(parser, text16, sizeof(text16)-1,
3701                                 XML_TRUE) == XML_STATUS_OK)
3702         fail("Failed to fault unclosed doc");
3703     if (found_rsqb == 0)
3704         fail("Did not catch the right square bracket");
3705 }
3706 END_TEST
3707 
3708 /* Test trailing right square bracket in an external entity parse */
3709 static int XMLCALL
external_entity_rsqb_catcher(XML_Parser parser,const XML_Char * context,const XML_Char * UNUSED_P (base),const XML_Char * UNUSED_P (systemId),const XML_Char * UNUSED_P (publicId))3710 external_entity_rsqb_catcher(XML_Parser parser,
3711                              const XML_Char *context,
3712                              const XML_Char *UNUSED_P(base),
3713                              const XML_Char *UNUSED_P(systemId),
3714                              const XML_Char *UNUSED_P(publicId))
3715 {
3716     const char *text = "<tag>]";
3717     XML_Parser ext_parser;
3718 
3719     ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3720     if (ext_parser == NULL)
3721         fail("Could not create external entity parser");
3722     XML_SetCharacterDataHandler(ext_parser, rsqb_handler);
3723     if (_XML_Parse_SINGLE_BYTES(ext_parser, text, strlen(text),
3724                                 XML_TRUE) != XML_STATUS_ERROR)
3725         fail("Async entity error not caught");
3726     if (XML_GetErrorCode(ext_parser) != XML_ERROR_ASYNC_ENTITY)
3727         xml_failure(ext_parser);
3728     XML_ParserFree(ext_parser);
3729     return XML_STATUS_OK;
3730 }
3731 
START_TEST(test_ext_entity_trailing_rsqb)3732 START_TEST(test_ext_entity_trailing_rsqb)
3733 {
3734     const char *text =
3735         "<!DOCTYPE doc [\n"
3736         "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
3737         "]>\n"
3738         "<doc>&en;</doc>";
3739     int found_rsqb;
3740 
3741     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3742     XML_SetExternalEntityRefHandler(parser, external_entity_rsqb_catcher);
3743     XML_SetUserData(parser, &found_rsqb);
3744     found_rsqb = 0;
3745     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
3746                                 XML_TRUE) != XML_STATUS_OK)
3747         xml_failure(parser);
3748     if (found_rsqb == 0)
3749         fail("No right square bracket found");
3750 }
3751 END_TEST
3752 
3753 /* Test CDATA handling in an external entity */
3754 static int XMLCALL
external_entity_good_cdata_ascii(XML_Parser parser,const XML_Char * context,const XML_Char * UNUSED_P (base),const XML_Char * UNUSED_P (systemId),const XML_Char * UNUSED_P (publicId))3755 external_entity_good_cdata_ascii(XML_Parser parser,
3756                                  const XML_Char *context,
3757                                  const XML_Char *UNUSED_P(base),
3758                                  const XML_Char *UNUSED_P(systemId),
3759                                  const XML_Char *UNUSED_P(publicId))
3760 {
3761     const char *text =
3762         "<a><![CDATA[<greeting>Hello, world!</greeting>]]></a>";
3763     const XML_Char *expected = XCS("<greeting>Hello, world!</greeting>");
3764     CharData storage;
3765     XML_Parser ext_parser;
3766 
3767     CharData_Init(&storage);
3768     ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3769     if (ext_parser == NULL)
3770         fail("Could not create external entity parser");
3771     XML_SetUserData(ext_parser, &storage);
3772     XML_SetCharacterDataHandler(ext_parser, accumulate_characters);
3773 
3774     if (_XML_Parse_SINGLE_BYTES(ext_parser, text, strlen(text),
3775                                 XML_TRUE) == XML_STATUS_ERROR)
3776         xml_failure(ext_parser);
3777     CharData_CheckXMLChars(&storage, expected);
3778 
3779     XML_ParserFree(ext_parser);
3780     return XML_STATUS_OK;
3781 }
3782 
START_TEST(test_ext_entity_good_cdata)3783 START_TEST(test_ext_entity_good_cdata)
3784 {
3785     const char *text =
3786         "<!DOCTYPE doc [\n"
3787         "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
3788         "]>\n"
3789         "<doc>&en;</doc>";
3790 
3791     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3792     XML_SetExternalEntityRefHandler(parser,
3793                                     external_entity_good_cdata_ascii);
3794     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
3795                                 XML_TRUE) != XML_STATUS_OK)
3796         xml_failure(parser);
3797 }
3798 END_TEST
3799 
3800 /* Test user parameter settings */
3801 /* Variable holding the expected handler userData */
3802 static void *handler_data = NULL;
3803 /* Count of the number of times the comment handler has been invoked */
3804 static int comment_count = 0;
3805 /* Count of the number of skipped entities */
3806 static int skip_count = 0;
3807 /* Count of the number of times the XML declaration handler is invoked */
3808 static int xdecl_count = 0;
3809 
3810 static void XMLCALL
xml_decl_handler(void * userData,const XML_Char * UNUSED_P (version),const XML_Char * UNUSED_P (encoding),int standalone)3811 xml_decl_handler(void *userData,
3812                  const XML_Char *UNUSED_P(version),
3813                  const XML_Char *UNUSED_P(encoding),
3814                  int standalone)
3815 {
3816     if (userData != handler_data)
3817         fail("User data (xml decl) not correctly set");
3818     if (standalone != -1)
3819         fail("Standalone not flagged as not present in XML decl");
3820     xdecl_count++;
3821 }
3822 
3823 static void XMLCALL
param_check_skip_handler(void * userData,const XML_Char * UNUSED_P (entityName),int UNUSED_P (is_parameter_entity))3824 param_check_skip_handler(void *userData,
3825                          const XML_Char *UNUSED_P(entityName),
3826                          int UNUSED_P(is_parameter_entity))
3827 {
3828     if (userData != handler_data)
3829         fail("User data (skip) not correctly set");
3830     skip_count++;
3831 }
3832 
3833 static void XMLCALL
data_check_comment_handler(void * userData,const XML_Char * UNUSED_P (data))3834 data_check_comment_handler(void *userData, const XML_Char *UNUSED_P(data))
3835 {
3836     /* Check that the userData passed through is what we expect */
3837     if (userData != handler_data)
3838         fail("User data (parser) not correctly set");
3839     /* Check that the user data in the parser is appropriate */
3840     if (XML_GetUserData(userData) != (void *)1)
3841         fail("User data in parser not correctly set");
3842     comment_count++;
3843 }
3844 
3845 static int XMLCALL
external_entity_param_checker(XML_Parser parser,const XML_Char * context,const XML_Char * UNUSED_P (base),const XML_Char * UNUSED_P (systemId),const XML_Char * UNUSED_P (publicId))3846 external_entity_param_checker(XML_Parser parser,
3847                               const XML_Char *context,
3848                               const XML_Char *UNUSED_P(base),
3849                               const XML_Char *UNUSED_P(systemId),
3850                               const XML_Char *UNUSED_P(publicId))
3851 {
3852     const char *text =
3853         "<!-- Subordinate parser -->\n"
3854         "<!ELEMENT doc (#PCDATA)*>";
3855     XML_Parser ext_parser;
3856 
3857     ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3858     if (ext_parser == NULL)
3859         fail("Could not create external entity parser");
3860     handler_data = ext_parser;
3861     if (_XML_Parse_SINGLE_BYTES(ext_parser, text, strlen(text),
3862                                 XML_TRUE) == XML_STATUS_ERROR) {
3863         xml_failure(parser);
3864         return XML_STATUS_ERROR;
3865     }
3866     handler_data = parser;
3867     XML_ParserFree(ext_parser);
3868     return XML_STATUS_OK;
3869 }
3870 
START_TEST(test_user_parameters)3871 START_TEST(test_user_parameters)
3872 {
3873     const char *text =
3874         "<?xml version='1.0' encoding='us-ascii'?>\n"
3875         "<!-- Primary parse -->\n"
3876         "<!DOCTYPE doc SYSTEM 'foo'>\n"
3877         "<doc>&entity;";
3878     const char *epilog =
3879         "<!-- Back to primary parser -->\n"
3880         "</doc>";
3881 
3882     comment_count = 0;
3883     skip_count = 0;
3884     xdecl_count = 0;
3885     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3886     XML_SetXmlDeclHandler(parser, xml_decl_handler);
3887     XML_SetExternalEntityRefHandler(parser, external_entity_param_checker);
3888     XML_SetCommentHandler(parser, data_check_comment_handler);
3889     XML_SetSkippedEntityHandler(parser, param_check_skip_handler);
3890     XML_UseParserAsHandlerArg(parser);
3891     XML_SetUserData(parser, (void *)1);
3892     handler_data = parser;
3893     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
3894                                 XML_FALSE) == XML_STATUS_ERROR)
3895         xml_failure(parser);
3896     if (comment_count != 2)
3897         fail("Comment handler not invoked enough times");
3898     /* Ensure we can't change policy mid-parse */
3899     if (XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_NEVER))
3900         fail("Changed param entity parsing policy while parsing");
3901     if (_XML_Parse_SINGLE_BYTES(parser, epilog, strlen(epilog),
3902                                 XML_TRUE) == XML_STATUS_ERROR)
3903         xml_failure(parser);
3904     if (comment_count != 3)
3905         fail("Comment handler not invoked enough times");
3906     if (skip_count != 1)
3907         fail("Skip handler not invoked enough times");
3908     if (xdecl_count != 1)
3909         fail("XML declaration handler not invoked");
3910 }
3911 END_TEST
3912 
3913 /* Test that an explicit external entity handler argument replaces
3914  * the parser as the first argument.
3915  *
3916  * We do not call the first parameter to the external entity handler
3917  * 'parser' for once, since the first time the handler is called it
3918  * will actually be a text string.  We need to be able to access the
3919  * global 'parser' variable to create our external entity parser from,
3920  * since there are code paths we need to ensure get executed.
3921  */
3922 static int XMLCALL
external_entity_ref_param_checker(XML_Parser parameter,const XML_Char * context,const XML_Char * UNUSED_P (base),const XML_Char * UNUSED_P (systemId),const XML_Char * UNUSED_P (publicId))3923 external_entity_ref_param_checker(XML_Parser parameter,
3924                                   const XML_Char *context,
3925                                   const XML_Char *UNUSED_P(base),
3926                                   const XML_Char *UNUSED_P(systemId),
3927                                   const XML_Char *UNUSED_P(publicId))
3928 {
3929     const char *text = "<!ELEMENT doc (#PCDATA)*>";
3930     XML_Parser ext_parser;
3931 
3932     if ((void *)parameter != handler_data)
3933         fail("External entity ref handler parameter not correct");
3934 
3935     /* Here we use the global 'parser' variable */
3936     ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3937     if (ext_parser == NULL)
3938         fail("Could not create external entity parser");
3939     if (_XML_Parse_SINGLE_BYTES(ext_parser, text, strlen(text),
3940                                 XML_TRUE) == XML_STATUS_ERROR)
3941         xml_failure(ext_parser);
3942 
3943     XML_ParserFree(ext_parser);
3944     return XML_STATUS_OK;
3945 }
3946 
START_TEST(test_ext_entity_ref_parameter)3947 START_TEST(test_ext_entity_ref_parameter)
3948 {
3949     const char *text =
3950         "<?xml version='1.0' encoding='us-ascii'?>\n"
3951         "<!DOCTYPE doc SYSTEM 'foo'>\n"
3952         "<doc>&entity;</doc>";
3953 
3954     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3955     XML_SetExternalEntityRefHandler(parser,
3956                                     external_entity_ref_param_checker);
3957     /* Set a handler arg that is not NULL and not parser (which is
3958      * what NULL would cause to be passed.
3959      */
3960     XML_SetExternalEntityRefHandlerArg(parser, (void *)text);
3961     handler_data = (void *)text;
3962     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
3963                                 XML_TRUE) == XML_STATUS_ERROR)
3964         xml_failure(parser);
3965 
3966     /* Now try again with unset args */
3967     XML_ParserReset(parser, NULL);
3968     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3969     XML_SetExternalEntityRefHandler(parser,
3970                                     external_entity_ref_param_checker);
3971     XML_SetExternalEntityRefHandlerArg(parser, NULL);
3972     handler_data = (void *)parser;
3973     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
3974                                 XML_TRUE) == XML_STATUS_ERROR)
3975         xml_failure(parser);
3976 }
3977 END_TEST
3978 
3979 /* Test the parsing of an empty string */
START_TEST(test_empty_parse)3980 START_TEST(test_empty_parse)
3981 {
3982     const char *text = "<doc></doc>";
3983     const char *partial = "<doc>";
3984 
3985     if (XML_Parse(parser, NULL, 0, XML_FALSE) == XML_STATUS_ERROR)
3986         fail("Parsing empty string faulted");
3987     if (XML_Parse(parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR)
3988         fail("Parsing final empty string not faulted");
3989     if (XML_GetErrorCode(parser) != XML_ERROR_NO_ELEMENTS)
3990         fail("Parsing final empty string faulted for wrong reason");
3991 
3992     /* Now try with valid text before the empty end */
3993     XML_ParserReset(parser, NULL);
3994     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
3995                                 XML_FALSE) == XML_STATUS_ERROR)
3996         xml_failure(parser);
3997     if (XML_Parse(parser, NULL, 0, XML_TRUE) == XML_STATUS_ERROR)
3998         fail("Parsing final empty string faulted");
3999 
4000     /* Now try with invalid text before the empty end */
4001     XML_ParserReset(parser, NULL);
4002     if (_XML_Parse_SINGLE_BYTES(parser, partial, strlen(partial),
4003                                 XML_FALSE) == XML_STATUS_ERROR)
4004         xml_failure(parser);
4005     if (XML_Parse(parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR)
4006         fail("Parsing final incomplete empty string not faulted");
4007 }
4008 END_TEST
4009 
4010 /* Test odd corners of the XML_GetBuffer interface */
4011 static enum XML_Status
get_feature(enum XML_FeatureEnum feature_id,long * presult)4012 get_feature(enum XML_FeatureEnum feature_id, long *presult)
4013 {
4014     const XML_Feature *feature = XML_GetFeatureList();
4015 
4016     if (feature == NULL)
4017         return XML_STATUS_ERROR;
4018     for (; feature->feature != XML_FEATURE_END; feature++) {
4019         if (feature->feature == feature_id) {
4020             *presult = feature->value;
4021             return XML_STATUS_OK;
4022         }
4023     }
4024     return XML_STATUS_ERROR;
4025 }
4026 
4027 /* Having an element name longer than 1024 characters exercises some
4028  * of the pool allocation code in the parser that otherwise does not
4029  * get executed.  The count at the end of the line is the number of
4030  * characters (bytes) in the element name by that point.x
4031  */
4032 static const char *get_buffer_test_text =
4033         "<documentwitharidiculouslylongelementnametotease" /* 0x030 */
4034         "aparticularcorneroftheallocationinXML_GetBuffers" /* 0x060 */
4035         "othatwecanimprovethecoverageyetagain012345678901" /* 0x090 */
4036         "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x0c0 */
4037         "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x0f0 */
4038         "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x120 */
4039         "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x150 */
4040         "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x180 */
4041         "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x1b0 */
4042         "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x1e0 */
4043         "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x210 */
4044         "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x240 */
4045         "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x270 */
4046         "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x2a0 */
4047         "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x2d0 */
4048         "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x300 */
4049         "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x330 */
4050         "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x360 */
4051         "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x390 */
4052         "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x3c0 */
4053         "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x3f0 */
4054         "123456789abcdef0123456789abcdef0123456789>\n<ef0"; /* 0x420 */
4055 
4056 /* Test odd corners of the XML_GetBuffer interface */
START_TEST(test_get_buffer_1)4057 START_TEST(test_get_buffer_1)
4058 {
4059     const char *text = get_buffer_test_text;
4060     void *buffer;
4061     long context_bytes;
4062 
4063     /* Attempt to allocate a negative length buffer */
4064     if (XML_GetBuffer(parser, -12) != NULL)
4065         fail("Negative length buffer not failed");
4066 
4067     /* Now get a small buffer and extend it past valid length */
4068     buffer = XML_GetBuffer(parser, 1536);
4069     if (buffer == NULL)
4070         fail("1.5K buffer failed");
4071     memcpy(buffer, text, strlen(text));
4072     if (XML_ParseBuffer(parser, strlen(text), XML_FALSE) == XML_STATUS_ERROR)
4073         xml_failure(parser);
4074     if (XML_GetBuffer(parser, INT_MAX) != NULL)
4075         fail("INT_MAX buffer not failed");
4076 
4077     /* Now try extending it a more reasonable but still too large
4078      * amount.  The allocator in XML_GetBuffer() doubles the buffer
4079      * size until it exceeds the requested amount or INT_MAX.  If it
4080      * exceeds INT_MAX, it rejects the request, so we want a request
4081      * between INT_MAX and INT_MAX/2.  A gap of 1K seems comfortable,
4082      * with an extra byte just to ensure that the request is off any
4083      * boundary.  The request will be inflated internally by
4084      * XML_CONTEXT_BYTES (if defined), so we subtract that from our
4085      * request.
4086      */
4087     if (get_feature(XML_FEATURE_CONTEXT_BYTES,
4088                     &context_bytes) != XML_STATUS_OK)
4089         context_bytes = 0;
4090     if (XML_GetBuffer(parser, INT_MAX - (context_bytes + 1025)) != NULL)
4091         fail("INT_MAX- buffer not failed");
4092 
4093     /* Now try extending it a carefully crafted amount */
4094     if (XML_GetBuffer(parser, 1000) == NULL)
4095         fail("1000 buffer failed");
4096 }
4097 END_TEST
4098 
4099 /* Test more corners of the XML_GetBuffer interface */
START_TEST(test_get_buffer_2)4100 START_TEST(test_get_buffer_2)
4101 {
4102     const char *text = get_buffer_test_text;
4103     void *buffer;
4104 
4105     /* Now get a decent buffer */
4106     buffer = XML_GetBuffer(parser, 1536);
4107     if (buffer == NULL)
4108         fail("1.5K buffer failed");
4109     memcpy(buffer, text, strlen(text));
4110     if (XML_ParseBuffer(parser, strlen(text), XML_FALSE) == XML_STATUS_ERROR)
4111         xml_failure(parser);
4112 
4113     /* Extend it, to catch a different code path */
4114     if (XML_GetBuffer(parser, 1024) == NULL)
4115         fail("1024 buffer failed");
4116 }
4117 END_TEST
4118 
4119 /* Test position information macros */
START_TEST(test_byte_info_at_end)4120 START_TEST(test_byte_info_at_end)
4121 {
4122     const char *text = "<doc></doc>";
4123 
4124     if (XML_GetCurrentByteIndex(parser) != -1 ||
4125         XML_GetCurrentByteCount(parser) != 0)
4126         fail("Byte index/count incorrect at start of parse");
4127     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
4128                                 XML_TRUE) == XML_STATUS_ERROR)
4129         xml_failure(parser);
4130     /* At end, the count will be zero and the index the end of string */
4131     if (XML_GetCurrentByteCount(parser) != 0)
4132         fail("Terminal byte count incorrect");
4133     if (XML_GetCurrentByteIndex(parser) != (XML_Index)strlen(text))
4134         fail("Terminal byte index incorrect");
4135 }
4136 END_TEST
4137 
4138 /* Test position information from errors */
4139 #define PRE_ERROR_STR  "<doc></"
4140 #define POST_ERROR_STR "wombat></doc>"
START_TEST(test_byte_info_at_error)4141 START_TEST(test_byte_info_at_error)
4142 {
4143     const char *text = PRE_ERROR_STR POST_ERROR_STR;
4144 
4145     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
4146                                 XML_TRUE) == XML_STATUS_OK)
4147         fail("Syntax error not faulted");
4148     if (XML_GetCurrentByteCount(parser) != 0)
4149         fail("Error byte count incorrect");
4150     if (XML_GetCurrentByteIndex(parser) != strlen(PRE_ERROR_STR))
4151         fail("Error byte index incorrect");
4152 }
4153 END_TEST
4154 #undef PRE_ERROR_STR
4155 #undef POST_ERROR_STR
4156 
4157 /* Test position information in handler */
4158 typedef struct ByteTestData {
4159     int start_element_len;
4160     int cdata_len;
4161     int total_string_len;
4162 } ByteTestData;
4163 
4164 static void
byte_character_handler(void * userData,const XML_Char * UNUSED_P (s),int len)4165 byte_character_handler(void *userData,
4166                        const XML_Char *UNUSED_P(s),
4167                        int len)
4168 {
4169 #ifdef XML_CONTEXT_BYTES
4170     int offset, size;
4171     const char *buffer;
4172     ByteTestData *data = (ByteTestData *)userData;
4173 
4174     buffer = XML_GetInputContext(parser, &offset, &size);
4175     if (buffer == NULL)
4176         fail("Failed to get context buffer");
4177     if (offset != data->start_element_len)
4178         fail("Context offset in unexpected position");
4179     if (len != data->cdata_len)
4180         fail("CDATA length reported incorrectly");
4181     if (size != data->total_string_len)
4182         fail("Context size is not full buffer");
4183     if (XML_GetCurrentByteIndex(parser) != offset)
4184         fail("Character byte index incorrect");
4185     if (XML_GetCurrentByteCount(parser) != len)
4186         fail("Character byte count incorrect");
4187 #else
4188     (void)userData;
4189     (void)len;
4190 #endif
4191 }
4192 
4193 #define START_ELEMENT "<e>"
4194 #define CDATA_TEXT    "Hello"
4195 #define END_ELEMENT   "</e>"
START_TEST(test_byte_info_at_cdata)4196 START_TEST(test_byte_info_at_cdata)
4197 {
4198     const char *text = START_ELEMENT CDATA_TEXT END_ELEMENT;
4199     int offset, size;
4200     ByteTestData data;
4201 
4202     /* Check initial context is empty */
4203     if (XML_GetInputContext(parser, &offset, &size) != NULL)
4204         fail("Unexpected context at start of parse");
4205 
4206     data.start_element_len = strlen(START_ELEMENT);
4207     data.cdata_len = strlen(CDATA_TEXT);
4208     data.total_string_len = strlen(text);
4209     XML_SetCharacterDataHandler(parser, byte_character_handler);
4210     XML_SetUserData(parser, &data);
4211     if (XML_Parse(parser, text, strlen(text), XML_TRUE) != XML_STATUS_OK)
4212         xml_failure(parser);
4213 }
4214 END_TEST
4215 #undef START_ELEMENT
4216 #undef CDATA_TEXT
4217 #undef END_ELEMENT
4218 
4219 /* Test predefined entities are correctly recognised */
START_TEST(test_predefined_entities)4220 START_TEST(test_predefined_entities)
4221 {
4222     const char *text = "<doc>&lt;&gt;&amp;&quot;&apos;</doc>";
4223     const XML_Char *expected = XCS("<doc>&lt;&gt;&amp;&quot;&apos;</doc>");
4224     const XML_Char *result = XCS("<>&\"'");
4225     CharData storage;
4226 
4227     XML_SetDefaultHandler(parser, accumulate_characters);
4228     /* run_character_check uses XML_SetCharacterDataHandler(), which
4229      * unfortunately heads off a code path that we need to exercise.
4230      */
4231     CharData_Init(&storage);
4232     XML_SetUserData(parser, &storage);
4233     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
4234                                 XML_TRUE) == XML_STATUS_ERROR)
4235         xml_failure(parser);
4236     /* The default handler doesn't translate the entities */
4237     CharData_CheckXMLChars(&storage, expected);
4238 
4239     /* Now try again and check the translation */
4240     XML_ParserReset(parser, NULL);
4241     run_character_check(text, result);
4242 }
4243 END_TEST
4244 
4245 /* Regression test that an invalid tag in an external parameter
4246  * reference in an external DTD is correctly faulted.
4247  *
4248  * Only a few specific tags are legal in DTDs ignoring comments and
4249  * processing instructions, all of which begin with an exclamation
4250  * mark.  "<el/>" is not one of them, so the parser should raise an
4251  * error on encountering it.
4252  */
4253 static int XMLCALL
external_entity_param(XML_Parser parser,const XML_Char * context,const XML_Char * UNUSED_P (base),const XML_Char * systemId,const XML_Char * UNUSED_P (publicId))4254 external_entity_param(XML_Parser parser,
4255                       const XML_Char *context,
4256                       const XML_Char *UNUSED_P(base),
4257                       const XML_Char *systemId,
4258                       const XML_Char *UNUSED_P(publicId))
4259 {
4260     const char *text1 =
4261         "<!ELEMENT doc EMPTY>\n"
4262         "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
4263         "<!ENTITY % e2 '%e1;'>\n"
4264         "%e1;\n";
4265     const char *text2 =
4266         "<!ELEMENT el EMPTY>\n"
4267         "<el/>\n";
4268     XML_Parser ext_parser;
4269 
4270     if (systemId == NULL)
4271         return XML_STATUS_OK;
4272 
4273     ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4274     if (ext_parser == NULL)
4275         fail("Could not create external entity parser");
4276 
4277     if (!xcstrcmp(systemId, XCS("004-1.ent"))) {
4278         if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, strlen(text1),
4279                                     XML_TRUE) != XML_STATUS_ERROR)
4280             fail("Inner DTD with invalid tag not rejected");
4281         if (XML_GetErrorCode(ext_parser) != XML_ERROR_EXTERNAL_ENTITY_HANDLING)
4282             xml_failure(ext_parser);
4283     }
4284     else if (!xcstrcmp(systemId, XCS("004-2.ent"))) {
4285         if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, strlen(text2),
4286                                     XML_TRUE) != XML_STATUS_ERROR)
4287             fail("Invalid tag in external param not rejected");
4288         if (XML_GetErrorCode(ext_parser) != XML_ERROR_SYNTAX)
4289             xml_failure(ext_parser);
4290     } else {
4291         fail("Unknown system ID");
4292     }
4293 
4294     XML_ParserFree(ext_parser);
4295     return XML_STATUS_ERROR;
4296 }
4297 
START_TEST(test_invalid_tag_in_dtd)4298 START_TEST(test_invalid_tag_in_dtd)
4299 {
4300     const char *text =
4301         "<!DOCTYPE doc SYSTEM '004-1.ent'>\n"
4302         "<doc></doc>\n";
4303 
4304     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4305     XML_SetExternalEntityRefHandler(parser, external_entity_param);
4306     expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
4307                    "Invalid tag IN DTD external param not rejected");
4308 }
4309 END_TEST
4310 
4311 /* Test entities not quite the predefined ones are not mis-recognised */
START_TEST(test_not_predefined_entities)4312 START_TEST(test_not_predefined_entities)
4313 {
4314     const char *text[] = {
4315         "<doc>&pt;</doc>",
4316         "<doc>&amo;</doc>",
4317         "<doc>&quid;</doc>",
4318         "<doc>&apod;</doc>",
4319         NULL
4320     };
4321     int i = 0;
4322 
4323     while (text[i] != NULL) {
4324         expect_failure(text[i], XML_ERROR_UNDEFINED_ENTITY,
4325                        "Undefined entity not rejected");
4326         XML_ParserReset(parser, NULL);
4327         i++;
4328     }
4329 }
4330 END_TEST
4331 
4332 /* Test conditional inclusion (IGNORE) */
4333 static int XMLCALL
external_entity_load_ignore(XML_Parser parser,const XML_Char * context,const XML_Char * UNUSED_P (base),const XML_Char * UNUSED_P (systemId),const XML_Char * UNUSED_P (publicId))4334 external_entity_load_ignore(XML_Parser parser,
4335                             const XML_Char *context,
4336                             const XML_Char *UNUSED_P(base),
4337                             const XML_Char *UNUSED_P(systemId),
4338                             const XML_Char *UNUSED_P(publicId))
4339 {
4340     const char *text = "<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>";
4341     XML_Parser ext_parser;
4342 
4343     ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4344     if (ext_parser == NULL)
4345         fail("Could not create external entity parser");
4346     if (_XML_Parse_SINGLE_BYTES(ext_parser, text, strlen(text),
4347                                 XML_TRUE) == XML_STATUS_ERROR)
4348         xml_failure(parser);
4349 
4350     XML_ParserFree(ext_parser);
4351     return XML_STATUS_OK;
4352 }
4353 
START_TEST(test_ignore_section)4354 START_TEST(test_ignore_section)
4355 {
4356     const char *text =
4357         "<!DOCTYPE doc SYSTEM 'foo'>\n"
4358         "<doc><e>&entity;</e></doc>";
4359     const XML_Char *expected =
4360         XCS("<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>\n&entity;");
4361     CharData storage;
4362 
4363     CharData_Init(&storage);
4364     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4365     XML_SetUserData(parser, &storage);
4366     XML_SetExternalEntityRefHandler(parser, external_entity_load_ignore);
4367     XML_SetDefaultHandler(parser, accumulate_characters);
4368     XML_SetStartDoctypeDeclHandler(parser, dummy_start_doctype_handler);
4369     XML_SetEndDoctypeDeclHandler(parser, dummy_end_doctype_handler);
4370     XML_SetElementDeclHandler(parser, dummy_element_decl_handler);
4371     XML_SetStartElementHandler(parser, dummy_start_element);
4372     XML_SetEndElementHandler(parser, dummy_end_element);
4373     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
4374                                 XML_TRUE) == XML_STATUS_ERROR)
4375         xml_failure(parser);
4376     CharData_CheckXMLChars(&storage, expected);
4377 }
4378 END_TEST
4379 
4380 static int XMLCALL
external_entity_load_ignore_utf16(XML_Parser parser,const XML_Char * context,const XML_Char * UNUSED_P (base),const XML_Char * UNUSED_P (systemId),const XML_Char * UNUSED_P (publicId))4381 external_entity_load_ignore_utf16(XML_Parser parser,
4382                                   const XML_Char *context,
4383                                   const XML_Char *UNUSED_P(base),
4384                                   const XML_Char *UNUSED_P(systemId),
4385                                   const XML_Char *UNUSED_P(publicId))
4386 {
4387     const char text[] =
4388         /* <![IGNORE[<!ELEMENT e (#PCDATA)*>]]> */
4389         "<\0!\0[\0I\0G\0N\0O\0R\0E\0[\0"
4390         "<\0!\0E\0L\0E\0M\0E\0N\0T\0 \0e\0 \0"
4391         "(\0#\0P\0C\0D\0A\0T\0A\0)\0*\0>\0]\0]\0>\0";
4392     XML_Parser ext_parser;
4393 
4394     ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4395     if (ext_parser == NULL)
4396         fail("Could not create external entity parser");
4397     if (_XML_Parse_SINGLE_BYTES(ext_parser, text, sizeof(text)-1,
4398                                 XML_TRUE) == XML_STATUS_ERROR)
4399         xml_failure(parser);
4400 
4401     XML_ParserFree(ext_parser);
4402     return XML_STATUS_OK;
4403 }
4404 
START_TEST(test_ignore_section_utf16)4405 START_TEST(test_ignore_section_utf16)
4406 {
4407     const char text[] =
4408         /* <!DOCTYPE d SYSTEM 's'> */
4409         "<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 "
4410         "\0S\0Y\0S\0T\0E\0M\0 \0'\0s\0'\0>\0\n\0"
4411         /* <d><e>&en;</e></d> */
4412         "<\0d\0>\0<\0e\0>\0&\0e\0n\0;\0<\0/\0e\0>\0<\0/\0d\0>\0";
4413     const XML_Char *expected =
4414         XCS("<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>\n&en;");
4415     CharData storage;
4416 
4417     CharData_Init(&storage);
4418     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4419     XML_SetUserData(parser, &storage);
4420     XML_SetExternalEntityRefHandler(parser,
4421                                     external_entity_load_ignore_utf16);
4422     XML_SetDefaultHandler(parser, accumulate_characters);
4423     XML_SetStartDoctypeDeclHandler(parser, dummy_start_doctype_handler);
4424     XML_SetEndDoctypeDeclHandler(parser, dummy_end_doctype_handler);
4425     XML_SetElementDeclHandler(parser, dummy_element_decl_handler);
4426     XML_SetStartElementHandler(parser, dummy_start_element);
4427     XML_SetEndElementHandler(parser, dummy_end_element);
4428     if (_XML_Parse_SINGLE_BYTES(parser, text, sizeof(text)-1,
4429                                 XML_TRUE) == XML_STATUS_ERROR)
4430         xml_failure(parser);
4431     CharData_CheckXMLChars(&storage, expected);
4432 }
4433 END_TEST
4434 
4435 static int XMLCALL
external_entity_load_ignore_utf16_be(XML_Parser parser,const XML_Char * context,const XML_Char * UNUSED_P (base),const XML_Char * UNUSED_P (systemId),const XML_Char * UNUSED_P (publicId))4436 external_entity_load_ignore_utf16_be(XML_Parser parser,
4437                                      const XML_Char *context,
4438                                      const XML_Char *UNUSED_P(base),
4439                                      const XML_Char *UNUSED_P(systemId),
4440                                      const XML_Char *UNUSED_P(publicId))
4441 {
4442     const char text[] =
4443         /* <![IGNORE[<!ELEMENT e (#PCDATA)*>]]> */
4444         "\0<\0!\0[\0I\0G\0N\0O\0R\0E\0["
4445         "\0<\0!\0E\0L\0E\0M\0E\0N\0T\0 \0e\0 "
4446         "\0(\0#\0P\0C\0D\0A\0T\0A\0)\0*\0>\0]\0]\0>";
4447     XML_Parser ext_parser;
4448 
4449     ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4450     if (ext_parser == NULL)
4451         fail("Could not create external entity parser");
4452     if (_XML_Parse_SINGLE_BYTES(ext_parser, text, sizeof(text)-1,
4453                                 XML_TRUE) == XML_STATUS_ERROR)
4454         xml_failure(parser);
4455 
4456     XML_ParserFree(ext_parser);
4457     return XML_STATUS_OK;
4458 }
4459 
START_TEST(test_ignore_section_utf16_be)4460 START_TEST(test_ignore_section_utf16_be)
4461 {
4462     const char text[] =
4463         /* <!DOCTYPE d SYSTEM 's'> */
4464         "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 "
4465         "\0S\0Y\0S\0T\0E\0M\0 \0'\0s\0'\0>\0\n"
4466         /* <d><e>&en;</e></d> */
4467         "\0<\0d\0>\0<\0e\0>\0&\0e\0n\0;\0<\0/\0e\0>\0<\0/\0d\0>";
4468     const XML_Char *expected =
4469         XCS("<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>\n&en;");
4470     CharData storage;
4471 
4472     CharData_Init(&storage);
4473     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4474     XML_SetUserData(parser, &storage);
4475     XML_SetExternalEntityRefHandler(parser,
4476                                     external_entity_load_ignore_utf16_be);
4477     XML_SetDefaultHandler(parser, accumulate_characters);
4478     XML_SetStartDoctypeDeclHandler(parser, dummy_start_doctype_handler);
4479     XML_SetEndDoctypeDeclHandler(parser, dummy_end_doctype_handler);
4480     XML_SetElementDeclHandler(parser, dummy_element_decl_handler);
4481     XML_SetStartElementHandler(parser, dummy_start_element);
4482     XML_SetEndElementHandler(parser, dummy_end_element);
4483     if (_XML_Parse_SINGLE_BYTES(parser, text, sizeof(text)-1,
4484                                 XML_TRUE) == XML_STATUS_ERROR)
4485         xml_failure(parser);
4486     CharData_CheckXMLChars(&storage, expected);
4487 }
4488 END_TEST
4489 
4490 /* Test mis-formatted conditional exclusion */
START_TEST(test_bad_ignore_section)4491 START_TEST(test_bad_ignore_section)
4492 {
4493     const char *text =
4494         "<!DOCTYPE doc SYSTEM 'foo'>\n"
4495         "<doc><e>&entity;</e></doc>";
4496     ExtFaults faults[] = {
4497         {
4498             "<![IGNORE[<!ELEM",
4499             "Broken-off declaration not faulted",
4500             NULL,
4501             XML_ERROR_SYNTAX
4502         },
4503         {
4504             "<![IGNORE[\x01]]>",
4505             "Invalid XML character not faulted",
4506             NULL,
4507             XML_ERROR_INVALID_TOKEN
4508         },
4509         {
4510             /* FIrst two bytes of a three-byte char */
4511             "<![IGNORE[\xe2\x82",
4512             "Partial XML character not faulted",
4513             NULL,
4514             XML_ERROR_PARTIAL_CHAR
4515         },
4516         { NULL, NULL, NULL, XML_ERROR_NONE }
4517     };
4518     ExtFaults *fault;
4519 
4520     for (fault = &faults[0]; fault->parse_text != NULL; fault++) {
4521         XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4522         XML_SetExternalEntityRefHandler(parser, external_entity_faulter);
4523         XML_SetUserData(parser, fault);
4524         expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
4525                        "Incomplete IGNORE section not failed");
4526         XML_ParserReset(parser, NULL);
4527     }
4528 }
4529 END_TEST
4530 
4531 /* Test recursive parsing */
4532 static int XMLCALL
external_entity_valuer(XML_Parser parser,const XML_Char * context,const XML_Char * UNUSED_P (base),const XML_Char * systemId,const XML_Char * UNUSED_P (publicId))4533 external_entity_valuer(XML_Parser parser,
4534                        const XML_Char *context,
4535                        const XML_Char *UNUSED_P(base),
4536                        const XML_Char *systemId,
4537                        const XML_Char *UNUSED_P(publicId))
4538 {
4539     const char *text1 =
4540         "<!ELEMENT doc EMPTY>\n"
4541         "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
4542         "<!ENTITY % e2 '%e1;'>\n"
4543         "%e1;\n";
4544     XML_Parser ext_parser;
4545 
4546     if (systemId == NULL)
4547         return XML_STATUS_OK;
4548     ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4549     if (ext_parser == NULL)
4550         fail("Could not create external entity parser");
4551     if (!xcstrcmp(systemId, XCS("004-1.ent"))) {
4552         if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, strlen(text1),
4553                                     XML_TRUE) == XML_STATUS_ERROR)
4554             xml_failure(ext_parser);
4555     }
4556     else if (!xcstrcmp(systemId, XCS("004-2.ent"))) {
4557         ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser);
4558         enum XML_Status status;
4559         enum XML_Error error;
4560 
4561         status = _XML_Parse_SINGLE_BYTES(ext_parser,
4562                                          fault->parse_text,
4563                                          strlen(fault->parse_text),
4564                                          XML_TRUE);
4565         if (fault->error == XML_ERROR_NONE) {
4566             if (status == XML_STATUS_ERROR)
4567                 xml_failure(ext_parser);
4568         } else {
4569             if (status != XML_STATUS_ERROR)
4570                 fail(fault->fail_text);
4571             error = XML_GetErrorCode(ext_parser);
4572             if (error != fault->error &&
4573                 (fault->error != XML_ERROR_XML_DECL ||
4574                  error != XML_ERROR_TEXT_DECL))
4575                 xml_failure(ext_parser);
4576         }
4577     }
4578 
4579     XML_ParserFree(ext_parser);
4580     return XML_STATUS_OK;
4581 }
4582 
START_TEST(test_external_entity_values)4583 START_TEST(test_external_entity_values)
4584 {
4585     const char *text =
4586         "<!DOCTYPE doc SYSTEM '004-1.ent'>\n"
4587         "<doc></doc>\n";
4588     ExtFaults data_004_2[] = {
4589         {
4590             "<!ATTLIST doc a1 CDATA 'value'>",
4591             NULL,
4592             NULL,
4593             XML_ERROR_NONE
4594         },
4595         {
4596             "<!ATTLIST $doc a1 CDATA 'value'>",
4597             "Invalid token not faulted",
4598             NULL,
4599             XML_ERROR_INVALID_TOKEN
4600         },
4601         {
4602             "'wombat",
4603             "Unterminated string not faulted",
4604             NULL,
4605             XML_ERROR_UNCLOSED_TOKEN
4606         },
4607         {
4608             "\xe2\x82",
4609             "Partial UTF-8 character not faulted",
4610             NULL,
4611             XML_ERROR_PARTIAL_CHAR
4612         },
4613         {
4614             "<?xml version='1.0' encoding='utf-8'?>\n",
4615             NULL,
4616             NULL,
4617             XML_ERROR_NONE
4618         },
4619         {
4620             "<?xml?>",
4621             "Malformed XML declaration not faulted",
4622             NULL,
4623             XML_ERROR_XML_DECL
4624         },
4625         {
4626             /* UTF-8 BOM */
4627             "\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>",
4628             NULL,
4629             NULL,
4630             XML_ERROR_NONE
4631         },
4632         {
4633             "<?xml version='1.0' encoding='utf-8'?>\n$",
4634             "Invalid token after text declaration not faulted",
4635             NULL,
4636             XML_ERROR_INVALID_TOKEN
4637         },
4638         {
4639             "<?xml version='1.0' encoding='utf-8'?>\n'wombat",
4640             "Unterminated string after text decl not faulted",
4641             NULL,
4642             XML_ERROR_UNCLOSED_TOKEN
4643         },
4644         {
4645             "<?xml version='1.0' encoding='utf-8'?>\n\xe2\x82",
4646             "Partial UTF-8 character after text decl not faulted",
4647             NULL,
4648             XML_ERROR_PARTIAL_CHAR
4649         },
4650         {
4651             "%e1;",
4652             "Recursive parameter entity not faulted",
4653             NULL,
4654             XML_ERROR_RECURSIVE_ENTITY_REF
4655         },
4656         { NULL, NULL, NULL, XML_ERROR_NONE }
4657     };
4658     int i;
4659 
4660     for (i = 0; data_004_2[i].parse_text != NULL; i++) {
4661         XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4662         XML_SetExternalEntityRefHandler(parser, external_entity_valuer);
4663         XML_SetUserData(parser, &data_004_2[i]);
4664         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
4665                                     XML_TRUE) == XML_STATUS_ERROR)
4666             xml_failure(parser);
4667         XML_ParserReset(parser, NULL);
4668     }
4669 }
4670 END_TEST
4671 
4672 /* Test the recursive parse interacts with a not standalone handler */
4673 static int XMLCALL
external_entity_not_standalone(XML_Parser parser,const XML_Char * context,const XML_Char * UNUSED_P (base),const XML_Char * systemId,const XML_Char * UNUSED_P (publicId))4674 external_entity_not_standalone(XML_Parser parser,
4675                                const XML_Char *context,
4676                                const XML_Char *UNUSED_P(base),
4677                                const XML_Char *systemId,
4678                                const XML_Char *UNUSED_P(publicId))
4679 {
4680     const char *text1 =
4681         "<!ELEMENT doc EMPTY>\n"
4682         "<!ENTITY % e1 SYSTEM 'bar'>\n"
4683         "%e1;\n";
4684     const char *text2 = "<!ATTLIST doc a1 CDATA 'value'>";
4685     XML_Parser ext_parser;
4686 
4687     if (systemId == NULL)
4688         return XML_STATUS_OK;
4689     ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4690     if (ext_parser == NULL)
4691         fail("Could not create external entity parser");
4692     if (!xcstrcmp(systemId, XCS("foo"))) {
4693         XML_SetNotStandaloneHandler(ext_parser,
4694                                     reject_not_standalone_handler);
4695         if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, strlen(text1),
4696                                     XML_TRUE) != XML_STATUS_ERROR)
4697             fail("Expected not standalone rejection");
4698         if (XML_GetErrorCode(ext_parser) != XML_ERROR_NOT_STANDALONE)
4699             xml_failure(ext_parser);
4700         XML_SetNotStandaloneHandler(ext_parser, NULL);
4701         XML_ParserFree(ext_parser);
4702         return XML_STATUS_ERROR;
4703     }
4704     else if (!xcstrcmp(systemId, XCS("bar"))) {
4705         if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, strlen(text2),
4706                                     XML_TRUE) == XML_STATUS_ERROR)
4707             xml_failure(ext_parser);
4708     }
4709 
4710     XML_ParserFree(ext_parser);
4711     return XML_STATUS_OK;
4712 }
4713 
START_TEST(test_ext_entity_not_standalone)4714 START_TEST(test_ext_entity_not_standalone)
4715 {
4716     const char *text =
4717         "<!DOCTYPE doc SYSTEM 'foo'>\n"
4718         "<doc></doc>";
4719 
4720     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4721     XML_SetExternalEntityRefHandler(parser, external_entity_not_standalone);
4722     expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
4723                    "Standalone rejection not caught");
4724 }
4725 END_TEST
4726 
4727 static int XMLCALL
external_entity_value_aborter(XML_Parser parser,const XML_Char * context,const XML_Char * UNUSED_P (base),const XML_Char * systemId,const XML_Char * UNUSED_P (publicId))4728 external_entity_value_aborter(XML_Parser parser,
4729                               const XML_Char *context,
4730                               const XML_Char *UNUSED_P(base),
4731                               const XML_Char *systemId,
4732                               const XML_Char *UNUSED_P(publicId))
4733 {
4734     const char *text1 =
4735         "<!ELEMENT doc EMPTY>\n"
4736         "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
4737         "<!ENTITY % e2 '%e1;'>\n"
4738         "%e1;\n";
4739     const char *text2 =
4740         "<?xml version='1.0' encoding='utf-8'?>";
4741     XML_Parser ext_parser;
4742 
4743     if (systemId == NULL)
4744         return XML_STATUS_OK;
4745     ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4746     if (ext_parser == NULL)
4747         fail("Could not create external entity parser");
4748     if (!xcstrcmp(systemId, XCS("004-1.ent"))) {
4749         if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, strlen(text1),
4750                                     XML_TRUE) == XML_STATUS_ERROR)
4751             xml_failure(ext_parser);
4752     }
4753     if (!xcstrcmp(systemId, XCS("004-2.ent"))) {
4754         XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
4755         XML_SetUserData(ext_parser, ext_parser);
4756         if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, strlen(text2),
4757                                     XML_TRUE) != XML_STATUS_ERROR)
4758             fail("Aborted parse not faulted");
4759         if (XML_GetErrorCode(ext_parser) != XML_ERROR_ABORTED)
4760             xml_failure(ext_parser);
4761     }
4762 
4763     XML_ParserFree(ext_parser);
4764     return XML_STATUS_OK;
4765 }
4766 
START_TEST(test_ext_entity_value_abort)4767 START_TEST(test_ext_entity_value_abort)
4768 {
4769     const char *text =
4770         "<!DOCTYPE doc SYSTEM '004-1.ent'>\n"
4771         "<doc></doc>\n";
4772 
4773     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4774     XML_SetExternalEntityRefHandler(parser,
4775                                     external_entity_value_aborter);
4776     resumable = XML_FALSE;
4777     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
4778                                 XML_TRUE) == XML_STATUS_ERROR)
4779         xml_failure(parser);
4780 }
4781 END_TEST
4782 
START_TEST(test_bad_public_doctype)4783 START_TEST(test_bad_public_doctype)
4784 {
4785     const char *text =
4786         "<?xml version='1.0' encoding='utf-8'?>\n"
4787         "<!DOCTYPE doc PUBLIC '{BadName}' 'test'>\n"
4788         "<doc></doc>";
4789 
4790     /* Setting a handler provokes a particular code path */
4791     XML_SetDoctypeDeclHandler(parser,
4792                               dummy_start_doctype_handler,
4793                               dummy_end_doctype_handler);
4794     expect_failure(text, XML_ERROR_PUBLICID, "Bad Public ID not failed");
4795 }
4796 END_TEST
4797 
4798 /* Test based on ibm/valid/P32/ibm32v04.xml */
START_TEST(test_attribute_enum_value)4799 START_TEST(test_attribute_enum_value)
4800 {
4801     const char *text =
4802         "<?xml version='1.0' standalone='no'?>\n"
4803         "<!DOCTYPE animal SYSTEM 'test.dtd'>\n"
4804         "<animal>This is a \n    <a/>  \n\nyellow tiger</animal>";
4805     ExtTest dtd_data = {
4806         "<!ELEMENT animal (#PCDATA|a)*>\n"
4807         "<!ELEMENT a EMPTY>\n"
4808         "<!ATTLIST animal xml:space (default|preserve) 'preserve'>",
4809         NULL,
4810         NULL
4811     };
4812     const XML_Char *expected = XCS("This is a \n      \n\nyellow tiger");
4813 
4814     XML_SetExternalEntityRefHandler(parser, external_entity_loader);
4815     XML_SetUserData(parser, &dtd_data);
4816     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4817     /* An attribute list handler provokes a different code path */
4818     XML_SetAttlistDeclHandler(parser, dummy_attlist_decl_handler);
4819     run_ext_character_check(text, &dtd_data, expected);
4820 }
4821 END_TEST
4822 
4823 /* Slightly bizarrely, the library seems to silently ignore entity
4824  * definitions for predefined entities, even when they are wrong.  The
4825  * language of the XML 1.0 spec is somewhat unhelpful as to what ought
4826  * to happen, so this is currently treated as acceptable.
4827  */
START_TEST(test_predefined_entity_redefinition)4828 START_TEST(test_predefined_entity_redefinition)
4829 {
4830     const char *text =
4831         "<!DOCTYPE doc [\n"
4832         "<!ENTITY apos 'foo'>\n"
4833         "]>\n"
4834         "<doc>&apos;</doc>";
4835     run_character_check(text, XCS("'"));
4836 }
4837 END_TEST
4838 
4839 /* Test that the parser stops processing the DTD after an unresolved
4840  * parameter entity is encountered.
4841  */
START_TEST(test_dtd_stop_processing)4842 START_TEST(test_dtd_stop_processing)
4843 {
4844     const char *text =
4845         "<!DOCTYPE doc [\n"
4846         "%foo;\n"
4847         "<!ENTITY bar 'bas'>\n"
4848         "]><doc/>";
4849 
4850     XML_SetEntityDeclHandler(parser, dummy_entity_decl_handler);
4851     dummy_handler_flags = 0;
4852     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
4853                                 XML_TRUE) == XML_STATUS_ERROR)
4854         xml_failure(parser);
4855     if (dummy_handler_flags != 0)
4856         fail("DTD processing still going after undefined PE");
4857 }
4858 END_TEST
4859 
4860 /* Test public notations with no system ID */
START_TEST(test_public_notation_no_sysid)4861 START_TEST(test_public_notation_no_sysid)
4862 {
4863     const char *text =
4864         "<!DOCTYPE doc [\n"
4865         "<!NOTATION note PUBLIC 'foo'>\n"
4866         "<!ELEMENT doc EMPTY>\n"
4867         "]>\n<doc/>";
4868 
4869     dummy_handler_flags = 0;
4870     XML_SetNotationDeclHandler(parser, dummy_notation_decl_handler);
4871     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
4872                                 XML_TRUE) == XML_STATUS_ERROR)
4873         xml_failure(parser);
4874     if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG)
4875         fail("Notation declaration handler not called");
4876 }
4877 END_TEST
4878 
4879 static void XMLCALL
record_element_start_handler(void * userData,const XML_Char * name,const XML_Char ** UNUSED_P (atts))4880 record_element_start_handler(void *userData,
4881                              const XML_Char *name,
4882                              const XML_Char **UNUSED_P(atts))
4883 {
4884     CharData_AppendXMLChars((CharData *)userData, name, xcstrlen(name));
4885 }
4886 
START_TEST(test_nested_groups)4887 START_TEST(test_nested_groups)
4888 {
4889     const char *text =
4890         "<!DOCTYPE doc [\n"
4891         "<!ELEMENT doc "
4892         /* Sixteen elements per line */
4893         "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,"
4894         "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?"
4895         "))))))))))))))))))))))))))))))))>\n"
4896         "<!ELEMENT e EMPTY>"
4897         "]>\n"
4898         "<doc><e/></doc>";
4899     CharData storage;
4900 
4901     CharData_Init(&storage);
4902     XML_SetElementDeclHandler(parser, dummy_element_decl_handler);
4903     XML_SetStartElementHandler(parser, record_element_start_handler);
4904     XML_SetUserData(parser, &storage);
4905     dummy_handler_flags = 0;
4906     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
4907                                 XML_TRUE) == XML_STATUS_ERROR)
4908         xml_failure(parser);
4909     CharData_CheckXMLChars(&storage, XCS("doce"));
4910     if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
4911         fail("Element handler not fired");
4912 }
4913 END_TEST
4914 
START_TEST(test_group_choice)4915 START_TEST(test_group_choice)
4916 {
4917     const char *text =
4918         "<!DOCTYPE doc [\n"
4919         "<!ELEMENT doc (a|b|c)+>\n"
4920         "<!ELEMENT a EMPTY>\n"
4921         "<!ELEMENT b (#PCDATA)>\n"
4922         "<!ELEMENT c ANY>\n"
4923         "]>\n"
4924         "<doc>\n"
4925         "<a/>\n"
4926         "<b attr='foo'>This is a foo</b>\n"
4927         "<c></c>\n"
4928         "</doc>\n";
4929 
4930     XML_SetElementDeclHandler(parser, dummy_element_decl_handler);
4931     dummy_handler_flags = 0;
4932     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
4933                                 XML_TRUE) == XML_STATUS_ERROR)
4934         xml_failure(parser);
4935     if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
4936         fail("Element handler flag not raised");
4937 }
4938 END_TEST
4939 
4940 static int XMLCALL
external_entity_public(XML_Parser parser,const XML_Char * context,const XML_Char * UNUSED_P (base),const XML_Char * systemId,const XML_Char * publicId)4941 external_entity_public(XML_Parser parser,
4942                        const XML_Char *context,
4943                        const XML_Char *UNUSED_P(base),
4944                        const XML_Char *systemId,
4945                        const XML_Char *publicId)
4946 {
4947     const char *text1 = (const char *)XML_GetUserData(parser);
4948     const char *text2 = "<!ATTLIST doc a CDATA 'value'>";
4949     const char *text = NULL;
4950     XML_Parser ext_parser;
4951     int parse_res;
4952 
4953     ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4954     if (ext_parser == NULL)
4955         return XML_STATUS_ERROR;
4956     if (systemId != NULL && !xcstrcmp(systemId, XCS("http://example.org/"))) {
4957         text = text1;
4958     }
4959     else if (publicId != NULL && !xcstrcmp(publicId, XCS("foo"))) {
4960         text = text2;
4961     }
4962     else
4963         fail("Unexpected parameters to external entity parser");
4964     parse_res = _XML_Parse_SINGLE_BYTES(ext_parser, text, strlen(text),
4965                                    XML_TRUE);
4966     XML_ParserFree(ext_parser);
4967     return parse_res;
4968 }
4969 
START_TEST(test_standalone_parameter_entity)4970 START_TEST(test_standalone_parameter_entity)
4971 {
4972     const char *text =
4973         "<?xml version='1.0' standalone='yes'?>\n"
4974         "<!DOCTYPE doc SYSTEM 'http://example.org/' [\n"
4975         "<!ENTITY % entity '<!ELEMENT doc (#PCDATA)>'>\n"
4976         "%entity;\n"
4977         "]>\n"
4978         "<doc></doc>";
4979     char dtd_data[] =
4980         "<!ENTITY % e1 'foo'>\n";
4981 
4982     XML_SetUserData(parser, dtd_data);
4983     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4984     XML_SetExternalEntityRefHandler(parser, external_entity_public);
4985     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
4986                                 XML_TRUE) == XML_STATUS_ERROR)
4987         xml_failure(parser);
4988 }
4989 END_TEST
4990 
4991 /* Test skipping of parameter entity in an external DTD */
4992 /* Derived from ibm/invalid/P69/ibm69i01.xml */
START_TEST(test_skipped_parameter_entity)4993 START_TEST(test_skipped_parameter_entity)
4994 {
4995     const char *text =
4996         "<?xml version='1.0'?>\n"
4997         "<!DOCTYPE root SYSTEM 'http://example.org/dtd.ent' [\n"
4998         "<!ELEMENT root (#PCDATA|a)* >\n"
4999         "]>\n"
5000         "<root></root>";
5001     ExtTest dtd_data = { "%pe2;", NULL, NULL };
5002 
5003     XML_SetExternalEntityRefHandler(parser, external_entity_loader);
5004     XML_SetUserData(parser, &dtd_data);
5005     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5006     XML_SetSkippedEntityHandler(parser, dummy_skip_handler);
5007     dummy_handler_flags = 0;
5008     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
5009                                 XML_TRUE) == XML_STATUS_ERROR)
5010         xml_failure(parser);
5011     if (dummy_handler_flags != DUMMY_SKIP_HANDLER_FLAG)
5012         fail("Skip handler not executed");
5013 }
5014 END_TEST
5015 
5016 /* Test recursive parameter entity definition rejected in external DTD */
START_TEST(test_recursive_external_parameter_entity)5017 START_TEST(test_recursive_external_parameter_entity)
5018 {
5019     const char *text =
5020         "<?xml version='1.0'?>\n"
5021         "<!DOCTYPE root SYSTEM 'http://example.org/dtd.ent' [\n"
5022         "<!ELEMENT root (#PCDATA|a)* >\n"
5023         "]>\n"
5024         "<root></root>";
5025     ExtFaults dtd_data = {
5026         "<!ENTITY % pe2 '&#37;pe2;'>\n%pe2;",
5027         "Recursive external parameter entity not faulted",
5028         NULL,
5029         XML_ERROR_RECURSIVE_ENTITY_REF
5030     };
5031 
5032     XML_SetExternalEntityRefHandler(parser, external_entity_faulter);
5033     XML_SetUserData(parser, &dtd_data);
5034     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5035     expect_failure(text,
5036                    XML_ERROR_EXTERNAL_ENTITY_HANDLING,
5037                    "Recursive external parameter not spotted");
5038 }
5039 END_TEST
5040 
5041 /* Test undefined parameter entity in external entity handler */
5042 static int XMLCALL
external_entity_devaluer(XML_Parser parser,const XML_Char * context,const XML_Char * UNUSED_P (base),const XML_Char * systemId,const XML_Char * UNUSED_P (publicId))5043 external_entity_devaluer(XML_Parser parser,
5044                          const XML_Char *context,
5045                          const XML_Char *UNUSED_P(base),
5046                          const XML_Char *systemId,
5047                          const XML_Char *UNUSED_P(publicId))
5048 {
5049     const char *text =
5050         "<!ELEMENT doc EMPTY>\n"
5051         "<!ENTITY % e1 SYSTEM 'bar'>\n"
5052         "%e1;\n";
5053     XML_Parser ext_parser;
5054     int clear_handler = (intptr_t)XML_GetUserData(parser);
5055 
5056     if (systemId == NULL || !xcstrcmp(systemId, XCS("bar")))
5057         return XML_STATUS_OK;
5058     if (xcstrcmp(systemId, XCS("foo")))
5059         fail("Unexpected system ID");
5060     ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
5061     if (ext_parser == NULL)
5062         fail("Could note create external entity parser");
5063     if (clear_handler)
5064         XML_SetExternalEntityRefHandler(ext_parser, NULL);
5065     if (_XML_Parse_SINGLE_BYTES(ext_parser, text, strlen(text),
5066                                 XML_TRUE) == XML_STATUS_ERROR)
5067         xml_failure(ext_parser);
5068 
5069     XML_ParserFree(ext_parser);
5070     return XML_STATUS_OK;
5071 }
5072 
START_TEST(test_undefined_ext_entity_in_external_dtd)5073 START_TEST(test_undefined_ext_entity_in_external_dtd)
5074 {
5075     const char *text =
5076         "<!DOCTYPE doc SYSTEM 'foo'>\n"
5077         "<doc></doc>\n";
5078 
5079     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5080     XML_SetExternalEntityRefHandler(parser, external_entity_devaluer);
5081     XML_SetUserData(parser, (void *)(intptr_t)XML_FALSE);
5082     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
5083                                 XML_TRUE) == XML_STATUS_ERROR)
5084         xml_failure(parser);
5085 
5086     /* Now repeat without the external entity ref handler invoking
5087      * another copy of itself.
5088      */
5089     XML_ParserReset(parser, NULL);
5090     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5091     XML_SetExternalEntityRefHandler(parser, external_entity_devaluer);
5092     XML_SetUserData(parser, (void *)(intptr_t)XML_TRUE);
5093     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
5094                                 XML_TRUE) == XML_STATUS_ERROR)
5095         xml_failure(parser);
5096 }
5097 END_TEST
5098 
5099 
5100 static void XMLCALL
aborting_xdecl_handler(void * UNUSED_P (userData),const XML_Char * UNUSED_P (version),const XML_Char * UNUSED_P (encoding),int UNUSED_P (standalone))5101 aborting_xdecl_handler(void           *UNUSED_P(userData),
5102                        const XML_Char *UNUSED_P(version),
5103                        const XML_Char *UNUSED_P(encoding),
5104                        int             UNUSED_P(standalone))
5105 {
5106     XML_StopParser(parser, resumable);
5107     XML_SetXmlDeclHandler(parser, NULL);
5108 }
5109 
5110 /* Test suspending the parse on receiving an XML declaration works */
START_TEST(test_suspend_xdecl)5111 START_TEST(test_suspend_xdecl)
5112 {
5113     const char *text = long_character_data_text;
5114 
5115     XML_SetXmlDeclHandler(parser, aborting_xdecl_handler);
5116     resumable = XML_TRUE;
5117     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
5118                                 XML_TRUE) != XML_STATUS_SUSPENDED)
5119         xml_failure(parser);
5120     if (XML_GetErrorCode(parser) != XML_ERROR_NONE)
5121         xml_failure(parser);
5122     /* Attempt to start a new parse while suspended */
5123     if (XML_Parse(parser, text, strlen(text), XML_TRUE) != XML_STATUS_ERROR)
5124         fail("Attempt to parse while suspended not faulted");
5125     if (XML_GetErrorCode(parser) != XML_ERROR_SUSPENDED)
5126         fail("Suspended parse not faulted with correct error");
5127 }
5128 END_TEST
5129 
5130 /* Test aborting the parse in an epilog works */
5131 static void XMLCALL
selective_aborting_default_handler(void * userData,const XML_Char * s,int len)5132 selective_aborting_default_handler(void *userData,
5133                                    const XML_Char *s,
5134                                    int len)
5135 {
5136     const XML_Char *match = (const XML_Char *)userData;
5137 
5138     if (match == NULL ||
5139         (xcstrlen(match) == (unsigned)len &&
5140          !xcstrncmp(match, s, len))) {
5141         XML_StopParser(parser, resumable);
5142         XML_SetDefaultHandler(parser, NULL);
5143     }
5144 }
5145 
START_TEST(test_abort_epilog)5146 START_TEST(test_abort_epilog)
5147 {
5148     const char *text = "<doc></doc>\n\r\n";
5149     XML_Char match[] = XCS("\r");
5150 
5151     XML_SetDefaultHandler(parser, selective_aborting_default_handler);
5152     XML_SetUserData(parser, match);
5153     resumable = XML_FALSE;
5154     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
5155                                 XML_TRUE) != XML_STATUS_ERROR)
5156         fail("Abort not triggered");
5157     if (XML_GetErrorCode(parser) != XML_ERROR_ABORTED)
5158         xml_failure(parser);
5159 }
5160 END_TEST
5161 
5162 /* Test a different code path for abort in the epilog */
START_TEST(test_abort_epilog_2)5163 START_TEST(test_abort_epilog_2)
5164 {
5165     const char *text = "<doc></doc>\n";
5166     XML_Char match[] = XCS("\n");
5167 
5168     XML_SetDefaultHandler(parser, selective_aborting_default_handler);
5169     XML_SetUserData(parser, match);
5170     resumable = XML_FALSE;
5171     expect_failure(text, XML_ERROR_ABORTED, "Abort not triggered");
5172 }
5173 END_TEST
5174 
5175 /* Test suspension from the epilog */
START_TEST(test_suspend_epilog)5176 START_TEST(test_suspend_epilog)
5177 {
5178     const char *text = "<doc></doc>\n";
5179     XML_Char match[] = XCS("\n");
5180 
5181     XML_SetDefaultHandler(parser, selective_aborting_default_handler);
5182     XML_SetUserData(parser, match);
5183     resumable = XML_TRUE;
5184     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
5185                                 XML_TRUE) != XML_STATUS_SUSPENDED)
5186         xml_failure(parser);
5187 }
5188 END_TEST
5189 
START_TEST(test_unfinished_epilog)5190 START_TEST(test_unfinished_epilog)
5191 {
5192     const char *text = "<doc></doc><";
5193 
5194     expect_failure(text, XML_ERROR_UNCLOSED_TOKEN,
5195                    "Incomplete epilog entry not faulted");
5196 }
5197 END_TEST
5198 
START_TEST(test_partial_char_in_epilog)5199 START_TEST(test_partial_char_in_epilog)
5200 {
5201     const char *text = "<doc></doc>\xe2\x82";
5202 
5203     /* First check that no fault is raised if the parse is not finished */
5204     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
5205                                 XML_FALSE) == XML_STATUS_ERROR)
5206         xml_failure(parser);
5207     /* Now check that it is faulted once we finish */
5208     if (XML_ParseBuffer(parser, 0, XML_TRUE) != XML_STATUS_ERROR)
5209         fail("Partial character in epilog not faulted");
5210     if (XML_GetErrorCode(parser) != XML_ERROR_PARTIAL_CHAR)
5211         xml_failure(parser);
5212 }
5213 END_TEST
5214 
START_TEST(test_hash_collision)5215 START_TEST(test_hash_collision)
5216 {
5217     /* For full coverage of the lookup routine, we need to ensure a
5218      * hash collision even though we can only tell that we have one
5219      * through breakpoint debugging or coverage statistics.  The
5220      * following will cause a hash collision on machines with a 64-bit
5221      * long type; others will have to experiment.  The full coverage
5222      * tests invoked from qa.sh usually provide a hash collision, but
5223      * not always.  This is an attempt to provide insurance.
5224      */
5225 #define COLLIDING_HASH_SALT (unsigned long)_SIP_ULL(0xffffffffU, 0xff99fc90U)
5226     const char * text =
5227         "<doc>\n"
5228         "<a1/><a2/><a3/><a4/><a5/><a6/><a7/><a8/>\n"
5229         "<b1></b1><b2 attr='foo'>This is a foo</b2><b3></b3><b4></b4>\n"
5230         "<b5></b5><b6></b6><b7></b7><b8></b8>\n"
5231         "<c1/><c2/><c3/><c4/><c5/><c6/><c7/><c8/>\n"
5232         "<d1/><d2/><d3/><d4/><d5/><d6/><d7/>\n"
5233         "<d8>This triggers the table growth and collides with b2</d8>\n"
5234         "</doc>\n";
5235 
5236     XML_SetHashSalt(parser, COLLIDING_HASH_SALT);
5237     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
5238                                 XML_TRUE) == XML_STATUS_ERROR)
5239         xml_failure(parser);
5240 }
5241 END_TEST
5242 #undef COLLIDING_HASH_SALT
5243 
5244 /* Test resuming a parse suspended in entity substitution */
5245 static void XMLCALL
start_element_suspender(void * UNUSED_P (userData),const XML_Char * name,const XML_Char ** UNUSED_P (atts))5246 start_element_suspender(void *UNUSED_P(userData),
5247                         const XML_Char *name,
5248                         const XML_Char **UNUSED_P(atts))
5249 {
5250     if (!xcstrcmp(name, XCS("suspend")))
5251         XML_StopParser(parser, XML_TRUE);
5252     if (!xcstrcmp(name, XCS("abort")))
5253         XML_StopParser(parser, XML_FALSE);
5254 }
5255 
START_TEST(test_suspend_resume_internal_entity)5256 START_TEST(test_suspend_resume_internal_entity)
5257 {
5258     const char *text =
5259         "<!DOCTYPE doc [\n"
5260         "<!ENTITY foo '<suspend>Hi<suspend>Ho</suspend></suspend>'>\n"
5261         "]>\n"
5262         "<doc>&foo;</doc>\n";
5263     const XML_Char *expected1 = XCS("Hi");
5264     const XML_Char *expected2 = XCS("HiHo");
5265     CharData storage;
5266 
5267     CharData_Init(&storage);
5268     XML_SetStartElementHandler(parser, start_element_suspender);
5269     XML_SetCharacterDataHandler(parser, accumulate_characters);
5270     XML_SetUserData(parser, &storage);
5271     if (XML_Parse(parser, text, strlen(text),
5272                   XML_TRUE) != XML_STATUS_SUSPENDED)
5273         xml_failure(parser);
5274     CharData_CheckXMLChars(&storage, XCS(""));
5275     if (XML_ResumeParser(parser) != XML_STATUS_SUSPENDED)
5276         xml_failure(parser);
5277     CharData_CheckXMLChars(&storage, expected1);
5278     if (XML_ResumeParser(parser) != XML_STATUS_OK)
5279         xml_failure(parser);
5280     CharData_CheckXMLChars(&storage, expected2);
5281 }
5282 END_TEST
5283 
5284 /* Test syntax error is caught at parse resumption */
START_TEST(test_resume_entity_with_syntax_error)5285 START_TEST(test_resume_entity_with_syntax_error)
5286 {
5287     const char *text =
5288         "<!DOCTYPE doc [\n"
5289         "<!ENTITY foo '<suspend>Hi</wombat>'>\n"
5290         "]>\n"
5291         "<doc>&foo;</doc>\n";
5292 
5293     XML_SetStartElementHandler(parser, start_element_suspender);
5294     if (XML_Parse(parser, text, strlen(text),
5295                   XML_TRUE) != XML_STATUS_SUSPENDED)
5296         xml_failure(parser);
5297     if (XML_ResumeParser(parser) != XML_STATUS_ERROR)
5298         fail("Syntax error in entity not faulted");
5299     if (XML_GetErrorCode(parser) != XML_ERROR_TAG_MISMATCH)
5300         xml_failure(parser);
5301 }
5302 END_TEST
5303 
5304 /* Test suspending and resuming in a parameter entity substitution */
5305 static void XMLCALL
element_decl_suspender(void * UNUSED_P (userData),const XML_Char * UNUSED_P (name),XML_Content * model)5306 element_decl_suspender(void *UNUSED_P(userData),
5307                        const XML_Char *UNUSED_P(name),
5308                        XML_Content *model)
5309 {
5310     XML_StopParser(parser, XML_TRUE);
5311     XML_FreeContentModel(parser, model);
5312 }
5313 
START_TEST(test_suspend_resume_parameter_entity)5314 START_TEST(test_suspend_resume_parameter_entity)
5315 {
5316     const char *text =
5317         "<!DOCTYPE doc [\n"
5318         "<!ENTITY % foo '<!ELEMENT doc (#PCDATA)*>'>\n"
5319         "%foo;\n"
5320         "]>\n"
5321         "<doc>Hello, world</doc>";
5322     const XML_Char *expected = XCS("Hello, world");
5323     CharData storage;
5324 
5325     CharData_Init(&storage);
5326     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5327     XML_SetElementDeclHandler(parser, element_decl_suspender);
5328     XML_SetCharacterDataHandler(parser, accumulate_characters);
5329     XML_SetUserData(parser, &storage);
5330     if (XML_Parse(parser, text, strlen(text),
5331                   XML_TRUE) != XML_STATUS_SUSPENDED)
5332         xml_failure(parser);
5333     CharData_CheckXMLChars(&storage, XCS(""));
5334     if (XML_ResumeParser(parser) != XML_STATUS_OK)
5335         xml_failure(parser);
5336     CharData_CheckXMLChars(&storage, expected);
5337 }
5338 END_TEST
5339 
5340 /* Test attempting to use parser after an error is faulted */
START_TEST(test_restart_on_error)5341 START_TEST(test_restart_on_error)
5342 {
5343     const char *text = "<$doc><doc></doc>";
5344 
5345     if (XML_Parse(parser, text, strlen(text), XML_TRUE) != XML_STATUS_ERROR)
5346         fail("Invalid tag name not faulted");
5347     if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN)
5348         xml_failure(parser);
5349     if (XML_Parse(parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR)
5350         fail("Restarting invalid parse not faulted");
5351     if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN)
5352         xml_failure(parser);
5353 }
5354 END_TEST
5355 
5356 /* Test that angle brackets in an attribute default value are faulted */
START_TEST(test_reject_lt_in_attribute_value)5357 START_TEST(test_reject_lt_in_attribute_value)
5358 {
5359     const char *text =
5360         "<!DOCTYPE doc [<!ATTLIST doc a CDATA '<bar>'>]>\n"
5361         "<doc></doc>";
5362 
5363     expect_failure(text, XML_ERROR_INVALID_TOKEN,
5364                    "Bad attribute default not faulted");
5365 }
5366 END_TEST
5367 
START_TEST(test_reject_unfinished_param_in_att_value)5368 START_TEST(test_reject_unfinished_param_in_att_value)
5369 {
5370     const char *text =
5371         "<!DOCTYPE doc [<!ATTLIST doc a CDATA '&foo'>]>\n"
5372         "<doc></doc>";
5373 
5374     expect_failure(text, XML_ERROR_INVALID_TOKEN,
5375                    "Bad attribute default not faulted");
5376 }
5377 END_TEST
5378 
START_TEST(test_trailing_cr_in_att_value)5379 START_TEST(test_trailing_cr_in_att_value)
5380 {
5381     const char *text = "<doc a='value\r'/>";
5382 
5383     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
5384                                 XML_TRUE) == XML_STATUS_ERROR)
5385         xml_failure(parser);
5386 }
5387 END_TEST
5388 
5389 /* Try parsing a general entity within a parameter entity in a
5390  * standalone internal DTD.  Covers a corner case in the parser.
5391  */
START_TEST(test_standalone_internal_entity)5392 START_TEST(test_standalone_internal_entity)
5393 {
5394     const char *text =
5395         "<?xml version='1.0' standalone='yes' ?>\n"
5396         "<!DOCTYPE doc [\n"
5397         "  <!ELEMENT doc (#PCDATA)>\n"
5398         "  <!ENTITY % pe '<!ATTLIST doc att2 CDATA \"&ge;\">'>\n"
5399         "  <!ENTITY ge 'AttDefaultValue'>\n"
5400         "  %pe;\n"
5401         "]>\n"
5402         "<doc att2='any'/>";
5403 
5404     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5405     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
5406                                 XML_TRUE) == XML_STATUS_ERROR)
5407         xml_failure(parser);
5408 }
5409 END_TEST
5410 
5411 /* Test that a reference to an unknown external entity is skipped */
START_TEST(test_skipped_external_entity)5412 START_TEST(test_skipped_external_entity)
5413 {
5414     const char *text =
5415         "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
5416         "<doc></doc>\n";
5417     ExtTest test_data = {
5418         "<!ELEMENT doc EMPTY>\n"
5419         "<!ENTITY % e2 '%e1;'>\n",
5420         NULL,
5421         NULL
5422     };
5423 
5424     XML_SetUserData(parser, &test_data);
5425     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5426     XML_SetExternalEntityRefHandler(parser, external_entity_loader);
5427     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
5428                                 XML_TRUE) == XML_STATUS_ERROR)
5429         xml_failure(parser);
5430 }
5431 END_TEST
5432 
5433 /* Test a different form of unknown external entity */
5434 typedef struct ext_hdlr_data {
5435     const char *parse_text;
5436     XML_ExternalEntityRefHandler handler;
5437 } ExtHdlrData;
5438 
5439 static int XMLCALL
external_entity_oneshot_loader(XML_Parser parser,const XML_Char * context,const XML_Char * UNUSED_P (base),const XML_Char * UNUSED_P (systemId),const XML_Char * UNUSED_P (publicId))5440 external_entity_oneshot_loader(XML_Parser parser,
5441                                const XML_Char *context,
5442                                const XML_Char *UNUSED_P(base),
5443                                const XML_Char *UNUSED_P(systemId),
5444                                const XML_Char *UNUSED_P(publicId))
5445 {
5446     ExtHdlrData *test_data = (ExtHdlrData *)XML_GetUserData(parser);
5447     XML_Parser ext_parser;
5448 
5449     ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
5450     if (ext_parser == NULL)
5451         fail("Could not create external entity parser.");
5452     /* Use the requested entity parser for further externals */
5453     XML_SetExternalEntityRefHandler(ext_parser, test_data->handler);
5454     if ( _XML_Parse_SINGLE_BYTES(ext_parser,
5455                                  test_data->parse_text,
5456                                  strlen(test_data->parse_text),
5457                                  XML_TRUE) == XML_STATUS_ERROR) {
5458         xml_failure(ext_parser);
5459     }
5460 
5461     XML_ParserFree(ext_parser);
5462     return XML_STATUS_OK;
5463 }
5464 
START_TEST(test_skipped_null_loaded_ext_entity)5465 START_TEST(test_skipped_null_loaded_ext_entity)
5466 {
5467     const char *text =
5468         "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n"
5469         "<doc />";
5470     ExtHdlrData test_data = {
5471         "<!ENTITY % pe1 SYSTEM 'http://example.org/two.ent'>\n"
5472         "<!ENTITY % pe2 '%pe1;'>\n"
5473         "%pe2;\n",
5474         external_entity_null_loader
5475     };
5476 
5477     XML_SetUserData(parser, &test_data);
5478     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5479     XML_SetExternalEntityRefHandler(parser, external_entity_oneshot_loader);
5480     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
5481                                 XML_TRUE) == XML_STATUS_ERROR)
5482         xml_failure(parser);
5483 }
5484 END_TEST
5485 
START_TEST(test_skipped_unloaded_ext_entity)5486 START_TEST(test_skipped_unloaded_ext_entity)
5487 {
5488     const char *text =
5489         "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n"
5490         "<doc />";
5491     ExtHdlrData test_data = {
5492         "<!ENTITY % pe1 SYSTEM 'http://example.org/two.ent'>\n"
5493         "<!ENTITY % pe2 '%pe1;'>\n"
5494         "%pe2;\n",
5495         NULL
5496     };
5497 
5498     XML_SetUserData(parser, &test_data);
5499     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5500     XML_SetExternalEntityRefHandler(parser, external_entity_oneshot_loader);
5501     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
5502                                 XML_TRUE) == XML_STATUS_ERROR)
5503         xml_failure(parser);
5504 }
5505 END_TEST
5506 
5507 /* Test that a parameter entity value ending with a carriage return
5508  * has it translated internally into a newline.
5509  */
START_TEST(test_param_entity_with_trailing_cr)5510 START_TEST(test_param_entity_with_trailing_cr)
5511 {
5512 #define PARAM_ENTITY_NAME "pe"
5513 #define PARAM_ENTITY_CORE_VALUE "<!ATTLIST doc att CDATA \"default\">"
5514     const char *text =
5515         "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
5516         "<doc/>";
5517     ExtTest test_data = {
5518         "<!ENTITY % " PARAM_ENTITY_NAME
5519         " '" PARAM_ENTITY_CORE_VALUE "\r'>\n"
5520         "%" PARAM_ENTITY_NAME ";\n",
5521         NULL,
5522         NULL
5523     };
5524 
5525     XML_SetUserData(parser, &test_data);
5526     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5527     XML_SetExternalEntityRefHandler(parser, external_entity_loader);
5528     XML_SetEntityDeclHandler(parser, param_entity_match_handler);
5529     entity_name_to_match = XCS(PARAM_ENTITY_NAME);
5530     entity_value_to_match = XCS(PARAM_ENTITY_CORE_VALUE) XCS("\n");
5531     entity_match_flag = ENTITY_MATCH_NOT_FOUND;
5532     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
5533                                 XML_TRUE) == XML_STATUS_ERROR)
5534         xml_failure(parser);
5535     if (entity_match_flag == ENTITY_MATCH_FAIL)
5536         fail("Parameter entity CR->NEWLINE conversion failed");
5537     else if (entity_match_flag == ENTITY_MATCH_NOT_FOUND)
5538         fail("Parameter entity not parsed");
5539 }
5540 #undef PARAM_ENTITY_NAME
5541 #undef PARAM_ENTITY_CORE_VALUE
5542 END_TEST
5543 
START_TEST(test_invalid_character_entity)5544 START_TEST(test_invalid_character_entity)
5545 {
5546     const char *text =
5547         "<!DOCTYPE doc [\n"
5548         "  <!ENTITY entity '&#x110000;'>\n"
5549         "]>\n"
5550         "<doc>&entity;</doc>";
5551 
5552     expect_failure(text, XML_ERROR_BAD_CHAR_REF,
5553                    "Out of range character reference not faulted");
5554 }
5555 END_TEST
5556 
START_TEST(test_invalid_character_entity_2)5557 START_TEST(test_invalid_character_entity_2)
5558 {
5559     const char *text =
5560         "<!DOCTYPE doc [\n"
5561         "  <!ENTITY entity '&#xg0;'>\n"
5562         "]>\n"
5563         "<doc>&entity;</doc>";
5564 
5565     expect_failure(text, XML_ERROR_INVALID_TOKEN,
5566                    "Out of range character reference not faulted");
5567 }
5568 END_TEST
5569 
START_TEST(test_invalid_character_entity_3)5570 START_TEST(test_invalid_character_entity_3)
5571 {
5572     const char text[] =
5573         /* <!DOCTYPE doc [\n */
5574         "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0\n"
5575         /* U+0E04 = KHO KHWAI
5576          * U+0E08 = CHO CHAN */
5577         /* <!ENTITY entity '&\u0e04\u0e08;'>\n */
5578         "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0e\0n\0t\0i\0t\0y\0 "
5579         "\0'\0&\x0e\x04\x0e\x08\0;\0'\0>\0\n"
5580         /* ]>\n */
5581         "\0]\0>\0\n"
5582         /* <doc>&entity;</doc> */
5583         "\0<\0d\0o\0c\0>\0&\0e\0n\0t\0i\0t\0y\0;\0<\0/\0d\0o\0c\0>";
5584 
5585     if (_XML_Parse_SINGLE_BYTES(parser, text, sizeof(text)-1,
5586                                 XML_TRUE) != XML_STATUS_ERROR)
5587         fail("Invalid start of entity name not faulted");
5588     if (XML_GetErrorCode(parser) != XML_ERROR_UNDEFINED_ENTITY)
5589         xml_failure(parser);
5590 }
5591 END_TEST
5592 
START_TEST(test_invalid_character_entity_4)5593 START_TEST(test_invalid_character_entity_4)
5594 {
5595     const char *text =
5596         "<!DOCTYPE doc [\n"
5597         "  <!ENTITY entity '&#1114112;'>\n" /* = &#x110000 */
5598         "]>\n"
5599         "<doc>&entity;</doc>";
5600 
5601     expect_failure(text, XML_ERROR_BAD_CHAR_REF,
5602                    "Out of range character reference not faulted");
5603 }
5604 END_TEST
5605 
5606 
5607 /* Test that processing instructions are picked up by a default handler */
START_TEST(test_pi_handled_in_default)5608 START_TEST(test_pi_handled_in_default)
5609 {
5610     const char *text = "<?test processing instruction?>\n<doc/>";
5611     const XML_Char *expected = XCS("<?test processing instruction?>\n<doc/>");
5612     CharData storage;
5613 
5614     CharData_Init(&storage);
5615     XML_SetDefaultHandler(parser, accumulate_characters);
5616     XML_SetUserData(parser, &storage);
5617     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
5618                                 XML_TRUE)== XML_STATUS_ERROR)
5619         xml_failure(parser);
5620     CharData_CheckXMLChars(&storage, expected);
5621 }
5622 END_TEST
5623 
5624 
5625 /* Test that comments are picked up by a default handler */
START_TEST(test_comment_handled_in_default)5626 START_TEST(test_comment_handled_in_default)
5627 {
5628     const char *text = "<!-- This is a comment -->\n<doc/>";
5629     const XML_Char *expected = XCS("<!-- This is a comment -->\n<doc/>");
5630     CharData storage;
5631 
5632     CharData_Init(&storage);
5633     XML_SetDefaultHandler(parser, accumulate_characters);
5634     XML_SetUserData(parser, &storage);
5635     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
5636                                 XML_TRUE) == XML_STATUS_ERROR)
5637         xml_failure(parser);
5638     CharData_CheckXMLChars(&storage, expected);
5639 }
5640 END_TEST
5641 
5642 /* Test PIs that look almost but not quite like XML declarations */
5643 static void XMLCALL
accumulate_pi_characters(void * userData,const XML_Char * target,const XML_Char * data)5644 accumulate_pi_characters(void *userData,
5645                          const XML_Char *target,
5646                          const XML_Char *data)
5647 {
5648     CharData *storage = (CharData *)userData;
5649 
5650     CharData_AppendXMLChars(storage, target, -1);
5651     CharData_AppendXMLChars(storage, XCS(": "), 2);
5652     CharData_AppendXMLChars(storage, data, -1);
5653     CharData_AppendXMLChars(storage, XCS("\n"), 1);
5654 }
5655 
START_TEST(test_pi_yml)5656 START_TEST(test_pi_yml)
5657 {
5658     const char *text = "<?yml something like data?><doc/>";
5659     const XML_Char *expected = XCS("yml: something like data\n");
5660     CharData storage;
5661 
5662     CharData_Init(&storage);
5663     XML_SetProcessingInstructionHandler(parser, accumulate_pi_characters);
5664     XML_SetUserData(parser, &storage);
5665     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
5666                                 XML_TRUE) == XML_STATUS_ERROR)
5667         xml_failure(parser);
5668     CharData_CheckXMLChars(&storage, expected);
5669 }
5670 END_TEST
5671 
START_TEST(test_pi_xnl)5672 START_TEST(test_pi_xnl)
5673 {
5674     const char *text = "<?xnl nothing like data?><doc/>";
5675     const XML_Char *expected = XCS("xnl: nothing like data\n");
5676     CharData storage;
5677 
5678     CharData_Init(&storage);
5679     XML_SetProcessingInstructionHandler(parser, accumulate_pi_characters);
5680     XML_SetUserData(parser, &storage);
5681     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
5682                                 XML_TRUE) == XML_STATUS_ERROR)
5683         xml_failure(parser);
5684     CharData_CheckXMLChars(&storage, expected);
5685 }
5686 END_TEST
5687 
START_TEST(test_pi_xmm)5688 START_TEST(test_pi_xmm)
5689 {
5690     const char *text = "<?xmm everything like data?><doc/>";
5691     const XML_Char *expected = XCS("xmm: everything like data\n");
5692     CharData storage;
5693 
5694     CharData_Init(&storage);
5695     XML_SetProcessingInstructionHandler(parser, accumulate_pi_characters);
5696     XML_SetUserData(parser, &storage);
5697     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
5698                                 XML_TRUE) == XML_STATUS_ERROR)
5699         xml_failure(parser);
5700     CharData_CheckXMLChars(&storage, expected);
5701 }
5702 END_TEST
5703 
START_TEST(test_utf16_pi)5704 START_TEST(test_utf16_pi)
5705 {
5706     const char text[] =
5707         /* <?{KHO KHWAI}{CHO CHAN}?>
5708          * where {KHO KHWAI} = U+0E04
5709          * and   {CHO CHAN}  = U+0E08
5710          */
5711         "<\0?\0\x04\x0e\x08\x0e?\0>\0"
5712         /* <q/> */
5713         "<\0q\0/\0>\0";
5714 #ifdef XML_UNICODE
5715     const XML_Char *expected = XCS("\x0e04\x0e08: \n");
5716 #else
5717     const XML_Char *expected = XCS("\xe0\xb8\x84\xe0\xb8\x88: \n");
5718 #endif
5719     CharData storage;
5720 
5721     CharData_Init(&storage);
5722     XML_SetProcessingInstructionHandler(parser, accumulate_pi_characters);
5723     XML_SetUserData(parser, &storage);
5724     if (_XML_Parse_SINGLE_BYTES(parser, text, sizeof(text)-1,
5725                                 XML_TRUE) == XML_STATUS_ERROR)
5726         xml_failure(parser);
5727     CharData_CheckXMLChars(&storage, expected);
5728 }
5729 END_TEST
5730 
START_TEST(test_utf16_be_pi)5731 START_TEST(test_utf16_be_pi)
5732 {
5733     const char text[] =
5734         /* <?{KHO KHWAI}{CHO CHAN}?>
5735          * where {KHO KHWAI} = U+0E04
5736          * and   {CHO CHAN}  = U+0E08
5737          */
5738         "\0<\0?\x0e\x04\x0e\x08\0?\0>"
5739         /* <q/> */
5740         "\0<\0q\0/\0>";
5741 #ifdef XML_UNICODE
5742     const XML_Char *expected = XCS("\x0e04\x0e08: \n");
5743 #else
5744     const XML_Char *expected = XCS("\xe0\xb8\x84\xe0\xb8\x88: \n");
5745 #endif
5746     CharData storage;
5747 
5748     CharData_Init(&storage);
5749     XML_SetProcessingInstructionHandler(parser, accumulate_pi_characters);
5750     XML_SetUserData(parser, &storage);
5751     if (_XML_Parse_SINGLE_BYTES(parser, text, sizeof(text)-1,
5752                                 XML_TRUE) == XML_STATUS_ERROR)
5753         xml_failure(parser);
5754     CharData_CheckXMLChars(&storage, expected);
5755 }
5756 END_TEST
5757 
5758 /* Test that comments can be picked up and translated */
5759 static void XMLCALL
accumulate_comment(void * userData,const XML_Char * data)5760 accumulate_comment(void *userData,
5761                    const XML_Char *data)
5762 {
5763     CharData *storage = (CharData *)userData;
5764 
5765     CharData_AppendXMLChars(storage, data, -1);
5766 }
5767 
START_TEST(test_utf16_be_comment)5768 START_TEST(test_utf16_be_comment)
5769 {
5770     const char text[] =
5771         /* <!-- Comment A --> */
5772         "\0<\0!\0-\0-\0 \0C\0o\0m\0m\0e\0n\0t\0 \0A\0 \0-\0-\0>\0\n"
5773         /* <doc/> */
5774         "\0<\0d\0o\0c\0/\0>";
5775     const XML_Char *expected = XCS(" Comment A ");
5776     CharData storage;
5777 
5778     CharData_Init(&storage);
5779     XML_SetCommentHandler(parser, accumulate_comment);
5780     XML_SetUserData(parser, &storage);
5781     if (_XML_Parse_SINGLE_BYTES(parser, text, sizeof(text)-1,
5782                                 XML_TRUE) == XML_STATUS_ERROR)
5783         xml_failure(parser);
5784     CharData_CheckXMLChars(&storage, expected);
5785 }
5786 END_TEST
5787 
START_TEST(test_utf16_le_comment)5788 START_TEST(test_utf16_le_comment)
5789 {
5790     const char text[] =
5791         /* <!-- Comment B --> */
5792         "<\0!\0-\0-\0 \0C\0o\0m\0m\0e\0n\0t\0 \0B\0 \0-\0-\0>\0\n\0"
5793         /* <doc/> */
5794         "<\0d\0o\0c\0/\0>\0";
5795     const XML_Char *expected = XCS(" Comment B ");
5796     CharData storage;
5797 
5798     CharData_Init(&storage);
5799     XML_SetCommentHandler(parser, accumulate_comment);
5800     XML_SetUserData(parser, &storage);
5801     if (_XML_Parse_SINGLE_BYTES(parser, text, sizeof(text)-1,
5802                                 XML_TRUE) == XML_STATUS_ERROR)
5803         xml_failure(parser);
5804     CharData_CheckXMLChars(&storage, expected);
5805 }
5806 END_TEST
5807 
5808 /* Test that the unknown encoding handler with map entries that expect
5809  * conversion but no conversion function is faulted
5810  */
5811 static int XMLCALL
failing_converter(void * UNUSED_P (data),const char * UNUSED_P (s))5812 failing_converter(void *UNUSED_P(data), const char *UNUSED_P(s))
5813 {
5814     /* Always claim to have failed */
5815     return -1;
5816 }
5817 
5818 static int XMLCALL
prefix_converter(void * UNUSED_P (data),const char * s)5819 prefix_converter(void *UNUSED_P(data), const char *s)
5820 {
5821     /* If the first byte is 0xff, raise an error */
5822     if (s[0] == (char)-1)
5823         return -1;
5824     /* Just add the low bits of the first byte to the second */
5825     return (s[1] + (s[0] & 0x7f)) & 0x01ff;
5826 }
5827 
5828 static int XMLCALL
MiscEncodingHandler(void * data,const XML_Char * encoding,XML_Encoding * info)5829 MiscEncodingHandler(void *data,
5830                     const XML_Char *encoding,
5831                     XML_Encoding *info)
5832 {
5833     int i;
5834     int high_map = -2; /* Assume a 2-byte sequence */
5835 
5836     if (!xcstrcmp(encoding, XCS("invalid-9")) ||
5837         !xcstrcmp(encoding, XCS("ascii-like")) ||
5838         !xcstrcmp(encoding, XCS("invalid-len")) ||
5839         !xcstrcmp(encoding, XCS("invalid-a")) ||
5840         !xcstrcmp(encoding, XCS("invalid-surrogate")) ||
5841         !xcstrcmp(encoding, XCS("invalid-high")))
5842         high_map = -1;
5843 
5844     for (i = 0; i < 128; ++i)
5845         info->map[i] = i;
5846     for (; i < 256; ++i)
5847         info->map[i] = high_map;
5848 
5849     /* If required, put an invalid value in the ASCII entries */
5850     if (!xcstrcmp(encoding, XCS("invalid-9")))
5851         info->map[9] = 5;
5852     /* If required, have a top-bit set character starts a 5-byte sequence */
5853     if (!xcstrcmp(encoding, XCS("invalid-len")))
5854         info->map[0x81] = -5;
5855     /* If required, make a top-bit set character a valid ASCII character */
5856     if (!xcstrcmp(encoding, XCS("invalid-a")))
5857         info->map[0x82] = 'a';
5858     /* If required, give a top-bit set character a forbidden value,
5859      * what would otherwise be the first of a surrogate pair.
5860      */
5861     if (!xcstrcmp(encoding, XCS("invalid-surrogate")))
5862         info->map[0x83] = 0xd801;
5863     /* If required, give a top-bit set character too high a value */
5864     if (!xcstrcmp(encoding, XCS("invalid-high")))
5865         info->map[0x84] = 0x010101;
5866 
5867     info->data = data;
5868     info->release = NULL;
5869     if (!xcstrcmp(encoding, XCS("failing-conv")))
5870         info->convert = failing_converter;
5871     else if (!xcstrcmp(encoding, XCS("prefix-conv")))
5872         info->convert = prefix_converter;
5873     else
5874         info->convert = NULL;
5875     return XML_STATUS_OK;
5876 }
5877 
START_TEST(test_missing_encoding_conversion_fn)5878 START_TEST(test_missing_encoding_conversion_fn)
5879 {
5880     const char *text =
5881         "<?xml version='1.0' encoding='no-conv'?>\n"
5882         "<doc>\x81</doc>";
5883 
5884     XML_SetUnknownEncodingHandler(parser, MiscEncodingHandler, NULL);
5885     /* MiscEncodingHandler sets up an encoding with every top-bit-set
5886      * character introducing a two-byte sequence.  For this, it
5887      * requires a convert function.  The above function call doesn't
5888      * pass one through, so when BadEncodingHandler actually gets
5889      * called it should supply an invalid encoding.
5890      */
5891     expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5892                    "Encoding with missing convert() not faulted");
5893 }
5894 END_TEST
5895 
START_TEST(test_failing_encoding_conversion_fn)5896 START_TEST(test_failing_encoding_conversion_fn)
5897 {
5898     const char *text =
5899         "<?xml version='1.0' encoding='failing-conv'?>\n"
5900         "<doc>\x81</doc>";
5901 
5902     XML_SetUnknownEncodingHandler(parser, MiscEncodingHandler, NULL);
5903     /* BadEncodingHandler sets up an encoding with every top-bit-set
5904      * character introducing a two-byte sequence.  For this, it
5905      * requires a convert function.  The above function call passes
5906      * one that insists all possible sequences are invalid anyway.
5907      */
5908     expect_failure(text, XML_ERROR_INVALID_TOKEN,
5909                    "Encoding with failing convert() not faulted");
5910 }
5911 END_TEST
5912 
5913 /* Test unknown encoding conversions */
START_TEST(test_unknown_encoding_success)5914 START_TEST(test_unknown_encoding_success)
5915 {
5916     const char *text =
5917         "<?xml version='1.0' encoding='prefix-conv'?>\n"
5918         /* Equivalent to <eoc>Hello, world</eoc> */
5919         "<\x81\x64\x80oc>Hello, world</\x81\x64\x80oc>";
5920 
5921     XML_SetUnknownEncodingHandler(parser, MiscEncodingHandler, NULL);
5922     run_character_check(text, XCS("Hello, world"));
5923 }
5924 END_TEST
5925 
5926 /* Test bad name character in unknown encoding */
START_TEST(test_unknown_encoding_bad_name)5927 START_TEST(test_unknown_encoding_bad_name)
5928 {
5929     const char *text =
5930         "<?xml version='1.0' encoding='prefix-conv'?>\n"
5931         "<\xff\x64oc>Hello, world</\xff\x64oc>";
5932 
5933     XML_SetUnknownEncodingHandler(parser, MiscEncodingHandler, NULL);
5934     expect_failure(text, XML_ERROR_INVALID_TOKEN,
5935                    "Bad name start in unknown encoding not faulted");
5936 }
5937 END_TEST
5938 
5939 /* Test bad mid-name character in unknown encoding */
START_TEST(test_unknown_encoding_bad_name_2)5940 START_TEST(test_unknown_encoding_bad_name_2)
5941 {
5942     const char *text =
5943         "<?xml version='1.0' encoding='prefix-conv'?>\n"
5944         "<d\xffoc>Hello, world</d\xffoc>";
5945 
5946     XML_SetUnknownEncodingHandler(parser, MiscEncodingHandler, NULL);
5947     expect_failure(text, XML_ERROR_INVALID_TOKEN,
5948                    "Bad name in unknown encoding not faulted");
5949 }
5950 END_TEST
5951 
5952 /* Test element name that is long enough to fill the conversion buffer
5953  * in an unknown encoding, finishing with an encoded character.
5954  */
START_TEST(test_unknown_encoding_long_name_1)5955 START_TEST(test_unknown_encoding_long_name_1)
5956 {
5957     const char *text =
5958         "<?xml version='1.0' encoding='prefix-conv'?>\n"
5959         "<abcdefghabcdefghabcdefghijkl\x80m\x80n\x80o\x80p>"
5960         "Hi"
5961         "</abcdefghabcdefghabcdefghijkl\x80m\x80n\x80o\x80p>";
5962     const XML_Char *expected = XCS("abcdefghabcdefghabcdefghijklmnop");
5963     CharData storage;
5964 
5965     CharData_Init(&storage);
5966     XML_SetUnknownEncodingHandler(parser, MiscEncodingHandler, NULL);
5967     XML_SetStartElementHandler(parser, record_element_start_handler);
5968     XML_SetUserData(parser, &storage);
5969     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
5970                                 XML_TRUE) == XML_STATUS_ERROR)
5971         xml_failure(parser);
5972     CharData_CheckXMLChars(&storage, expected);
5973 }
5974 END_TEST
5975 
5976 /* Test element name that is long enough to fill the conversion buffer
5977  * in an unknown encoding, finishing with an simple character.
5978  */
START_TEST(test_unknown_encoding_long_name_2)5979 START_TEST(test_unknown_encoding_long_name_2)
5980 {
5981     const char *text =
5982         "<?xml version='1.0' encoding='prefix-conv'?>\n"
5983         "<abcdefghabcdefghabcdefghijklmnop>"
5984         "Hi"
5985         "</abcdefghabcdefghabcdefghijklmnop>";
5986     const XML_Char *expected = XCS("abcdefghabcdefghabcdefghijklmnop");
5987     CharData storage;
5988 
5989     CharData_Init(&storage);
5990     XML_SetUnknownEncodingHandler(parser, MiscEncodingHandler, NULL);
5991     XML_SetStartElementHandler(parser, record_element_start_handler);
5992     XML_SetUserData(parser, &storage);
5993     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
5994                                 XML_TRUE) == XML_STATUS_ERROR)
5995         xml_failure(parser);
5996     CharData_CheckXMLChars(&storage, expected);
5997 }
5998 END_TEST
5999 
START_TEST(test_invalid_unknown_encoding)6000 START_TEST(test_invalid_unknown_encoding)
6001 {
6002     const char *text =
6003         "<?xml version='1.0' encoding='invalid-9'?>\n"
6004         "<doc>Hello world</doc>";
6005 
6006     XML_SetUnknownEncodingHandler(parser, MiscEncodingHandler, NULL);
6007     expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
6008                    "Invalid unknown encoding not faulted");
6009 }
6010 END_TEST
6011 
START_TEST(test_unknown_ascii_encoding_ok)6012 START_TEST(test_unknown_ascii_encoding_ok)
6013 {
6014     const char *text =
6015         "<?xml version='1.0' encoding='ascii-like'?>\n"
6016         "<doc>Hello, world</doc>";
6017 
6018     XML_SetUnknownEncodingHandler(parser, MiscEncodingHandler, NULL);
6019     run_character_check(text, XCS("Hello, world"));
6020 }
6021 END_TEST
6022 
START_TEST(test_unknown_ascii_encoding_fail)6023 START_TEST(test_unknown_ascii_encoding_fail)
6024 {
6025     const char *text =
6026         "<?xml version='1.0' encoding='ascii-like'?>\n"
6027         "<doc>Hello, \x80 world</doc>";
6028 
6029     XML_SetUnknownEncodingHandler(parser, MiscEncodingHandler, NULL);
6030     expect_failure(text, XML_ERROR_INVALID_TOKEN,
6031                    "Invalid character not faulted");
6032 }
6033 END_TEST
6034 
START_TEST(test_unknown_encoding_invalid_length)6035 START_TEST(test_unknown_encoding_invalid_length)
6036 {
6037     const char *text =
6038         "<?xml version='1.0' encoding='invalid-len'?>\n"
6039         "<doc>Hello, world</doc>";
6040 
6041     XML_SetUnknownEncodingHandler(parser, MiscEncodingHandler, NULL);
6042     expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
6043                    "Invalid unknown encoding not faulted");
6044 }
6045 END_TEST
6046 
START_TEST(test_unknown_encoding_invalid_topbit)6047 START_TEST(test_unknown_encoding_invalid_topbit)
6048 {
6049     const char *text =
6050         "<?xml version='1.0' encoding='invalid-a'?>\n"
6051         "<doc>Hello, world</doc>";
6052 
6053     XML_SetUnknownEncodingHandler(parser, MiscEncodingHandler, NULL);
6054     expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
6055                    "Invalid unknown encoding not faulted");
6056 }
6057 END_TEST
6058 
START_TEST(test_unknown_encoding_invalid_surrogate)6059 START_TEST(test_unknown_encoding_invalid_surrogate)
6060 {
6061     const char *text =
6062         "<?xml version='1.0' encoding='invalid-surrogate'?>\n"
6063         "<doc>Hello, \x82 world</doc>";
6064 
6065     XML_SetUnknownEncodingHandler(parser, MiscEncodingHandler, NULL);
6066     expect_failure(text, XML_ERROR_INVALID_TOKEN,
6067                    "Invalid unknown encoding not faulted");
6068 }
6069 END_TEST
6070 
START_TEST(test_unknown_encoding_invalid_high)6071 START_TEST(test_unknown_encoding_invalid_high)
6072 {
6073     const char *text =
6074         "<?xml version='1.0' encoding='invalid-high'?>\n"
6075         "<doc>Hello, world</doc>";
6076 
6077     XML_SetUnknownEncodingHandler(parser, MiscEncodingHandler, NULL);
6078     expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
6079                    "Invalid unknown encoding not faulted");
6080 }
6081 END_TEST
6082 
START_TEST(test_unknown_encoding_invalid_attr_value)6083 START_TEST(test_unknown_encoding_invalid_attr_value)
6084 {
6085     const char *text =
6086         "<?xml version='1.0' encoding='prefix-conv'?>\n"
6087         "<doc attr='\xff\x30'/>";
6088 
6089     XML_SetUnknownEncodingHandler(parser, MiscEncodingHandler, NULL);
6090     expect_failure(text, XML_ERROR_INVALID_TOKEN,
6091                    "Invalid attribute valid not faulted");
6092 }
6093 END_TEST
6094 
6095 /* Test an external entity parser set to use latin-1 detects UTF-16
6096  * BOMs correctly.
6097  */
6098 enum ee_parse_flags {
6099     EE_PARSE_NONE = 0x00,
6100     EE_PARSE_FULL_BUFFER = 0x01
6101 };
6102 
6103 typedef struct ExtTest2 {
6104     const char *parse_text;
6105     int parse_len;
6106     const XML_Char *encoding;
6107     CharData *storage;
6108     enum ee_parse_flags flags;
6109 } ExtTest2;
6110 
6111 static int XMLCALL
external_entity_loader2(XML_Parser parser,const XML_Char * context,const XML_Char * UNUSED_P (base),const XML_Char * UNUSED_P (systemId),const XML_Char * UNUSED_P (publicId))6112 external_entity_loader2(XML_Parser parser,
6113                         const XML_Char *context,
6114                         const XML_Char *UNUSED_P(base),
6115                         const XML_Char *UNUSED_P(systemId),
6116                         const XML_Char *UNUSED_P(publicId))
6117 {
6118     ExtTest2 *test_data = (ExtTest2 *)XML_GetUserData(parser);
6119     XML_Parser extparser;
6120 
6121     extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
6122     if (extparser == NULL)
6123         fail("Coulr not create external entity parser");
6124     if (test_data->encoding != NULL) {
6125         if (!XML_SetEncoding(extparser, test_data->encoding))
6126             fail("XML_SetEncoding() ignored for external entity");
6127     }
6128     if (test_data->flags & EE_PARSE_FULL_BUFFER) {
6129         if (XML_Parse(extparser,
6130                       test_data->parse_text,
6131                       test_data->parse_len,
6132                       XML_TRUE) == XML_STATUS_ERROR) {
6133             xml_failure(extparser);
6134         }
6135     }
6136     else if (_XML_Parse_SINGLE_BYTES(extparser,
6137                                      test_data->parse_text,
6138                                      test_data->parse_len,
6139                                      XML_TRUE) == XML_STATUS_ERROR) {
6140         xml_failure(extparser);
6141     }
6142 
6143     XML_ParserFree(extparser);
6144     return XML_STATUS_OK;
6145 }
6146 
6147 /* Test that UTF-16 BOM does not select UTF-16 given explicit encoding */
6148 static void XMLCALL
ext2_accumulate_characters(void * userData,const XML_Char * s,int len)6149 ext2_accumulate_characters(void *userData, const XML_Char *s, int len)
6150 {
6151     ExtTest2 *test_data = (ExtTest2 *)userData;
6152     accumulate_characters(test_data->storage, s, len);
6153 }
6154 
START_TEST(test_ext_entity_latin1_utf16le_bom)6155 START_TEST(test_ext_entity_latin1_utf16le_bom)
6156 {
6157     const char *text =
6158         "<!DOCTYPE doc [\n"
6159         "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
6160         "]>\n"
6161         "<doc>&en;</doc>";
6162     ExtTest2 test_data = {
6163         /* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */
6164         /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn,
6165          *   0x4c = L and 0x20 is a space
6166          */
6167         "\xff\xfe\x4c\x20",
6168         4,
6169         XCS("iso-8859-1"),
6170         NULL,
6171         EE_PARSE_NONE
6172     };
6173 #ifdef XML_UNICODE
6174     const XML_Char *expected = XCS("\x00ff\x00feL ");
6175 #else
6176     /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */
6177     const XML_Char *expected = XCS("\xc3\xbf\xc3\xbeL ");
6178 #endif
6179     CharData storage;
6180 
6181 
6182     CharData_Init(&storage);
6183     test_data.storage = &storage;
6184     XML_SetExternalEntityRefHandler(parser, external_entity_loader2);
6185     XML_SetUserData(parser, &test_data);
6186     XML_SetCharacterDataHandler(parser, ext2_accumulate_characters);
6187     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
6188                                 XML_TRUE) == XML_STATUS_ERROR)
6189         xml_failure(parser);
6190     CharData_CheckXMLChars(&storage, expected);
6191 }
6192 END_TEST
6193 
START_TEST(test_ext_entity_latin1_utf16be_bom)6194 START_TEST(test_ext_entity_latin1_utf16be_bom)
6195 {
6196     const char *text =
6197         "<!DOCTYPE doc [\n"
6198         "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
6199         "]>\n"
6200         "<doc>&en;</doc>";
6201     ExtTest2 test_data = {
6202         /* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */
6203         /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn,
6204          *   0x4c = L and 0x20 is a space
6205          */
6206         "\xfe\xff\x20\x4c",
6207         4,
6208         XCS("iso-8859-1"),
6209         NULL,
6210         EE_PARSE_NONE
6211     };
6212 #ifdef XML_UNICODE
6213     const XML_Char *expected = XCS("\x00fe\x00ff L");
6214 #else
6215     /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */
6216     const XML_Char *expected = XCS("\xc3\xbe\xc3\xbf L");
6217 #endif
6218     CharData storage;
6219 
6220 
6221     CharData_Init(&storage);
6222     test_data.storage = &storage;
6223     XML_SetExternalEntityRefHandler(parser, external_entity_loader2);
6224     XML_SetUserData(parser, &test_data);
6225     XML_SetCharacterDataHandler(parser, ext2_accumulate_characters);
6226     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
6227                                 XML_TRUE) == XML_STATUS_ERROR)
6228         xml_failure(parser);
6229     CharData_CheckXMLChars(&storage, expected);
6230 }
6231 END_TEST
6232 
6233 
6234 /* Parsing the full buffer rather than a byte at a time makes a
6235  * difference to the encoding scanning code, so repeat the above tests
6236  * without breaking them down by byte.
6237  */
START_TEST(test_ext_entity_latin1_utf16le_bom2)6238 START_TEST(test_ext_entity_latin1_utf16le_bom2)
6239 {
6240     const char *text =
6241         "<!DOCTYPE doc [\n"
6242         "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
6243         "]>\n"
6244         "<doc>&en;</doc>";
6245     ExtTest2 test_data = {
6246         /* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */
6247         /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn,
6248          *   0x4c = L and 0x20 is a space
6249          */
6250         "\xff\xfe\x4c\x20",
6251         4,
6252         XCS("iso-8859-1"),
6253         NULL,
6254         EE_PARSE_FULL_BUFFER
6255     };
6256 #ifdef XML_UNICODE
6257     const XML_Char *expected = XCS("\x00ff\x00feL ");
6258 #else
6259     /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */
6260     const XML_Char *expected = XCS("\xc3\xbf\xc3\xbeL ");
6261 #endif
6262     CharData storage;
6263 
6264 
6265     CharData_Init(&storage);
6266     test_data.storage = &storage;
6267     XML_SetExternalEntityRefHandler(parser, external_entity_loader2);
6268     XML_SetUserData(parser, &test_data);
6269     XML_SetCharacterDataHandler(parser, ext2_accumulate_characters);
6270     if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
6271         xml_failure(parser);
6272     CharData_CheckXMLChars(&storage, expected);
6273 }
6274 END_TEST
6275 
START_TEST(test_ext_entity_latin1_utf16be_bom2)6276 START_TEST(test_ext_entity_latin1_utf16be_bom2)
6277 {
6278     const char *text =
6279         "<!DOCTYPE doc [\n"
6280         "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
6281         "]>\n"
6282         "<doc>&en;</doc>";
6283     ExtTest2 test_data = {
6284         /* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */
6285         /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn,
6286          *   0x4c = L and 0x20 is a space
6287          */
6288         "\xfe\xff\x20\x4c",
6289         4,
6290         XCS("iso-8859-1"),
6291         NULL,
6292         EE_PARSE_FULL_BUFFER
6293     };
6294 #ifdef XML_UNICODE
6295     const XML_Char *expected = XCS("\x00fe\x00ff L");
6296 #else
6297     /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */
6298     const XML_Char *expected = "\xc3\xbe\xc3\xbf L";
6299 #endif
6300     CharData storage;
6301 
6302 
6303     CharData_Init(&storage);
6304     test_data.storage = &storage;
6305     XML_SetExternalEntityRefHandler(parser, external_entity_loader2);
6306     XML_SetUserData(parser, &test_data);
6307     XML_SetCharacterDataHandler(parser, ext2_accumulate_characters);
6308     if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
6309         xml_failure(parser);
6310     CharData_CheckXMLChars(&storage, expected);
6311 }
6312 END_TEST
6313 
6314 /* Test little-endian UTF-16 given an explicit big-endian encoding */
START_TEST(test_ext_entity_utf16_be)6315 START_TEST(test_ext_entity_utf16_be)
6316 {
6317     const char *text =
6318         "<!DOCTYPE doc [\n"
6319         "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
6320         "]>\n"
6321         "<doc>&en;</doc>";
6322     ExtTest2 test_data = {
6323         "<\0e\0/\0>\0",
6324         8,
6325         XCS("utf-16be"),
6326         NULL,
6327         EE_PARSE_NONE
6328     };
6329 #ifdef XML_UNICODE
6330     const XML_Char *expected = XCS("\x3c00\x6500\x2f00\x3e00");
6331 #else
6332     const XML_Char *expected =
6333         XCS("\xe3\xb0\x80"   /* U+3C00 */
6334             "\xe6\x94\x80"   /* U+6500 */
6335             "\xe2\xbc\x80"   /* U+2F00 */
6336             "\xe3\xb8\x80"); /* U+3E00 */
6337 #endif
6338     CharData storage;
6339 
6340     CharData_Init(&storage);
6341     test_data.storage = &storage;
6342     XML_SetExternalEntityRefHandler(parser, external_entity_loader2);
6343     XML_SetUserData(parser, &test_data);
6344     XML_SetCharacterDataHandler(parser, ext2_accumulate_characters);
6345     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
6346                                 XML_TRUE) == XML_STATUS_ERROR)
6347         xml_failure(parser);
6348     CharData_CheckXMLChars(&storage, expected);
6349 }
6350 END_TEST
6351 
6352 /* Test big-endian UTF-16 given an explicit little-endian encoding */
START_TEST(test_ext_entity_utf16_le)6353 START_TEST(test_ext_entity_utf16_le)
6354 {
6355     const char *text =
6356         "<!DOCTYPE doc [\n"
6357         "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
6358         "]>\n"
6359         "<doc>&en;</doc>";
6360     ExtTest2 test_data = {
6361         "\0<\0e\0/\0>",
6362         8,
6363         XCS("utf-16le"),
6364         NULL,
6365         EE_PARSE_NONE
6366     };
6367 #ifdef XML_UNICODE
6368     const XML_Char *expected = XCS("\x3c00\x6500\x2f00\x3e00");
6369 #else
6370     const XML_Char *expected =
6371         XCS("\xe3\xb0\x80"   /* U+3C00 */
6372             "\xe6\x94\x80"   /* U+6500 */
6373             "\xe2\xbc\x80"   /* U+2F00 */
6374             "\xe3\xb8\x80"); /* U+3E00 */
6375 #endif
6376     CharData storage;
6377 
6378     CharData_Init(&storage);
6379     test_data.storage = &storage;
6380     XML_SetExternalEntityRefHandler(parser, external_entity_loader2);
6381     XML_SetUserData(parser, &test_data);
6382     XML_SetCharacterDataHandler(parser, ext2_accumulate_characters);
6383     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
6384                                 XML_TRUE) == XML_STATUS_ERROR)
6385         xml_failure(parser);
6386     CharData_CheckXMLChars(&storage, expected);
6387 }
6388 END_TEST
6389 
6390 /* Test little-endian UTF-16 given no explicit encoding.
6391  * The existing default encoding (UTF-8) is assumed to hold without a
6392  * BOM to contradict it, so the entity value will in fact provoke an
6393  * error because 0x00 is not a valid XML character.  We parse the
6394  * whole buffer in one go rather than feeding it in byte by byte to
6395  * exercise different code paths in the initial scanning routines.
6396  */
6397 typedef struct ExtFaults2 {
6398     const char *parse_text;
6399     int parse_len;
6400     const char *fail_text;
6401     const XML_Char *encoding;
6402     enum XML_Error error;
6403 } ExtFaults2;
6404 
6405 static int XMLCALL
external_entity_faulter2(XML_Parser parser,const XML_Char * context,const XML_Char * UNUSED_P (base),const XML_Char * UNUSED_P (systemId),const XML_Char * UNUSED_P (publicId))6406 external_entity_faulter2(XML_Parser parser,
6407                          const XML_Char *context,
6408                          const XML_Char *UNUSED_P(base),
6409                          const XML_Char *UNUSED_P(systemId),
6410                          const XML_Char *UNUSED_P(publicId))
6411 {
6412     ExtFaults2 *test_data = (ExtFaults2 *)XML_GetUserData(parser);
6413     XML_Parser extparser;
6414 
6415     extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
6416     if (extparser == NULL)
6417         fail("Could not create external entity parser");
6418     if (test_data->encoding != NULL) {
6419         if (!XML_SetEncoding(extparser, test_data->encoding))
6420             fail("XML_SetEncoding() ignored for external entity");
6421     }
6422     if (XML_Parse(extparser,
6423                   test_data->parse_text,
6424                   test_data->parse_len,
6425                   XML_TRUE) != XML_STATUS_ERROR)
6426         fail(test_data->fail_text);
6427     if (XML_GetErrorCode(extparser) != test_data->error)
6428         xml_failure(extparser);
6429 
6430     XML_ParserFree(extparser);
6431     return XML_STATUS_ERROR;
6432 }
6433 
START_TEST(test_ext_entity_utf16_unknown)6434 START_TEST(test_ext_entity_utf16_unknown)
6435 {
6436     const char *text =
6437         "<!DOCTYPE doc [\n"
6438         "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
6439         "]>\n"
6440         "<doc>&en;</doc>";
6441     ExtFaults2 test_data = {
6442         "a\0b\0c\0",
6443         6,
6444         "Invalid character in entity not faulted",
6445         NULL,
6446         XML_ERROR_INVALID_TOKEN
6447     };
6448 
6449     XML_SetExternalEntityRefHandler(parser, external_entity_faulter2);
6450     XML_SetUserData(parser, &test_data);
6451     expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
6452                    "Invalid character should not have been accepted");
6453 }
6454 END_TEST
6455 
6456 /* Test not-quite-UTF-8 BOM (0xEF 0xBB 0xBF) */
START_TEST(test_ext_entity_utf8_non_bom)6457 START_TEST(test_ext_entity_utf8_non_bom)
6458 {
6459     const char *text =
6460         "<!DOCTYPE doc [\n"
6461         "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
6462         "]>\n"
6463         "<doc>&en;</doc>";
6464     ExtTest2 test_data = {
6465         "\xef\xbb\x80", /* Arabic letter DAD medial form, U+FEC0 */
6466         3,
6467         NULL,
6468         NULL,
6469         EE_PARSE_NONE
6470     };
6471 #ifdef XML_UNICODE
6472     const XML_Char *expected = XCS("\xfec0");
6473 #else
6474     const XML_Char *expected = XCS("\xef\xbb\x80");
6475 #endif
6476     CharData storage;
6477 
6478     CharData_Init(&storage);
6479     test_data.storage = &storage;
6480     XML_SetExternalEntityRefHandler(parser, external_entity_loader2);
6481     XML_SetUserData(parser, &test_data);
6482     XML_SetCharacterDataHandler(parser, ext2_accumulate_characters);
6483     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
6484                                 XML_TRUE) == XML_STATUS_ERROR)
6485         xml_failure(parser);
6486     CharData_CheckXMLChars(&storage, expected);
6487 }
6488 END_TEST
6489 
6490 /* Test that UTF-8 in a CDATA section is correctly passed through */
START_TEST(test_utf8_in_cdata_section)6491 START_TEST(test_utf8_in_cdata_section)
6492 {
6493     const char *text = "<doc><![CDATA[one \xc3\xa9 two]]></doc>";
6494 #ifdef XML_UNICODE
6495     const XML_Char *expected = XCS("one \x00e9 two");
6496 #else
6497     const XML_Char *expected = XCS("one \xc3\xa9 two");
6498 #endif
6499 
6500     run_character_check(text, expected);
6501 }
6502 END_TEST
6503 
6504 /* Test that little-endian UTF-16 in a CDATA section is handled */
START_TEST(test_utf8_in_cdata_section_2)6505 START_TEST(test_utf8_in_cdata_section_2)
6506 {
6507     const char *text = "<doc><![CDATA[\xc3\xa9]\xc3\xa9two]]></doc>";
6508 #ifdef XML_UNICODE
6509     const XML_Char *expected = XCS("\x00e9]\x00e9two");
6510 #else
6511     const XML_Char *expected = XCS("\xc3\xa9]\xc3\xa9two");
6512 #endif
6513 
6514     run_character_check(text, expected);
6515 }
6516 END_TEST
6517 
6518 /* Test trailing spaces in elements are accepted */
6519 static void XMLCALL
record_element_end_handler(void * userData,const XML_Char * name)6520 record_element_end_handler(void *userData,
6521                            const XML_Char *name)
6522 {
6523     CharData *storage = (CharData *)userData;
6524 
6525     CharData_AppendXMLChars(storage, XCS("/"), 1);
6526     CharData_AppendXMLChars(storage, name, -1);
6527 }
6528 
START_TEST(test_trailing_spaces_in_elements)6529 START_TEST(test_trailing_spaces_in_elements)
6530 {
6531     const char *text = "<doc   >Hi</doc >";
6532     const XML_Char *expected = XCS("doc/doc");
6533     CharData storage;
6534 
6535     CharData_Init(&storage);
6536     XML_SetElementHandler(parser, record_element_start_handler,
6537                           record_element_end_handler);
6538     XML_SetUserData(parser, &storage);
6539     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
6540                                 XML_TRUE) == XML_STATUS_ERROR)
6541         xml_failure(parser);
6542     CharData_CheckXMLChars(&storage, expected);
6543 }
6544 END_TEST
6545 
START_TEST(test_utf16_attribute)6546 START_TEST(test_utf16_attribute)
6547 {
6548     const char text[] =
6549         /* <d {KHO KHWAI}{CHO CHAN}='a'/>
6550          * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
6551          * and   {CHO CHAN}  = U+0E08 = 0xe0 0xb8 0x88 in UTF-8
6552          */
6553         "<\0d\0 \0\x04\x0e\x08\x0e=\0'\0a\0'\0/\0>\0";
6554     const XML_Char *expected = XCS("a");
6555     CharData storage;
6556 
6557     CharData_Init(&storage);
6558     XML_SetStartElementHandler(parser, accumulate_attribute);
6559     XML_SetUserData(parser, &storage);
6560     if (_XML_Parse_SINGLE_BYTES(parser, text, sizeof(text)-1,
6561                                 XML_TRUE) == XML_STATUS_ERROR)
6562         xml_failure(parser);
6563     CharData_CheckXMLChars(&storage, expected);
6564 }
6565 END_TEST
6566 
START_TEST(test_utf16_second_attr)6567 START_TEST(test_utf16_second_attr)
6568 {
6569     /* <d a='1' {KHO KHWAI}{CHO CHAN}='2'/>
6570          * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
6571          * and   {CHO CHAN}  = U+0E08 = 0xe0 0xb8 0x88 in UTF-8
6572          */
6573     const char text[] =
6574         "<\0d\0 \0a\0=\0'\0\x31\0'\0 \0"
6575         "\x04\x0e\x08\x0e=\0'\0\x32\0'\0/\0>\0";
6576     const XML_Char *expected = XCS("1");
6577     CharData storage;
6578 
6579     CharData_Init(&storage);
6580     XML_SetStartElementHandler(parser, accumulate_attribute);
6581     XML_SetUserData(parser, &storage);
6582     if (_XML_Parse_SINGLE_BYTES(parser, text, sizeof(text)-1,
6583                                 XML_TRUE) == XML_STATUS_ERROR)
6584         xml_failure(parser);
6585     CharData_CheckXMLChars(&storage, expected);
6586 }
6587 END_TEST
6588 
START_TEST(test_attr_after_solidus)6589 START_TEST(test_attr_after_solidus)
6590 {
6591     const char *text = "<doc attr1='a' / attr2='b'>";
6592 
6593     expect_failure(text, XML_ERROR_INVALID_TOKEN,
6594                    "Misplaced / not faulted");
6595 }
6596 END_TEST
6597 
6598 static void XMLCALL
accumulate_entity_decl(void * userData,const XML_Char * entityName,int UNUSED_P (is_parameter_entity),const XML_Char * value,int value_length,const XML_Char * UNUSED_P (base),const XML_Char * UNUSED_P (systemId),const XML_Char * UNUSED_P (publicId),const XML_Char * UNUSED_P (notationName))6599 accumulate_entity_decl(void *userData,
6600                        const XML_Char *entityName,
6601                        int UNUSED_P(is_parameter_entity),
6602                        const XML_Char *value,
6603                        int value_length,
6604                        const XML_Char *UNUSED_P(base),
6605                        const XML_Char *UNUSED_P(systemId),
6606                        const XML_Char *UNUSED_P(publicId),
6607                        const XML_Char *UNUSED_P(notationName))
6608 {
6609     CharData *storage = (CharData *)userData;
6610 
6611     CharData_AppendXMLChars(storage, entityName, -1);
6612     CharData_AppendXMLChars(storage, XCS("="), 1);
6613     CharData_AppendXMLChars(storage, value, value_length);
6614     CharData_AppendXMLChars(storage, XCS("\n"), 1);
6615 }
6616 
6617 
START_TEST(test_utf16_pe)6618 START_TEST(test_utf16_pe)
6619 {
6620     /* <!DOCTYPE doc [
6621      * <!ENTITY % {KHO KHWAI}{CHO CHAN} '<!ELEMENT doc (#PCDATA)>'>
6622      * %{KHO KHWAI}{CHO CHAN};
6623      * ]>
6624      * <doc></doc>
6625      *
6626      * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
6627      * and   {CHO CHAN}  = U+0E08 = 0xe0 0xb8 0x88 in UTF-8
6628      */
6629     const char text[] =
6630         "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0\n"
6631         "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \x0e\x04\x0e\x08\0 "
6632         "\0'\0<\0!\0E\0L\0E\0M\0E\0N\0T\0 "
6633         "\0d\0o\0c\0 \0(\0#\0P\0C\0D\0A\0T\0A\0)\0>\0'\0>\0\n"
6634         "\0%\x0e\x04\x0e\x08\0;\0\n"
6635         "\0]\0>\0\n"
6636         "\0<\0d\0o\0c\0>\0<\0/\0d\0o\0c\0>";
6637 #ifdef XML_UNICODE
6638     const XML_Char *expected =
6639         XCS("\x0e04\x0e08=<!ELEMENT doc (#PCDATA)>\n");
6640 #else
6641     const XML_Char *expected =
6642         XCS("\xe0\xb8\x84\xe0\xb8\x88=<!ELEMENT doc (#PCDATA)>\n");
6643 #endif
6644     CharData storage;
6645 
6646     CharData_Init(&storage);
6647     XML_SetUserData(parser, &storage);
6648     XML_SetEntityDeclHandler(parser, accumulate_entity_decl);
6649     if (_XML_Parse_SINGLE_BYTES(parser, text, sizeof(text)-1,
6650                                 XML_TRUE) == XML_STATUS_ERROR)
6651         xml_failure(parser);
6652     CharData_CheckXMLChars(&storage, expected);
6653 }
6654 END_TEST
6655 
6656 /* Test that duff attribute description keywords are rejected */
START_TEST(test_bad_attr_desc_keyword)6657 START_TEST(test_bad_attr_desc_keyword)
6658 {
6659     const char *text =
6660         "<!DOCTYPE doc [\n"
6661         "  <!ATTLIST doc attr CDATA #!IMPLIED>\n"
6662         "]>\n"
6663         "<doc />";
6664 
6665     expect_failure(text, XML_ERROR_INVALID_TOKEN,
6666                    "Bad keyword !IMPLIED not faulted");
6667 }
6668 END_TEST
6669 
6670 /* Test that an invalid attribute description keyword consisting of
6671  * UTF-16 characters with their top bytes non-zero are correctly
6672  * faulted
6673  */
START_TEST(test_bad_attr_desc_keyword_utf16)6674 START_TEST(test_bad_attr_desc_keyword_utf16)
6675 {
6676     /* <!DOCTYPE d [
6677      * <!ATTLIST d a CDATA #{KHO KHWAI}{CHO CHAN}>
6678      * ]><d/>
6679      *
6680      * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
6681      * and   {CHO CHAN}  = U+0E08 = 0xe0 0xb8 0x88 in UTF-8
6682      */
6683     const char text[] =
6684         "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n"
6685         "\0<\0!\0A\0T\0T\0L\0I\0S\0T\0 \0d\0 \0a\0 \0C\0D\0A\0T\0A\0 "
6686         "\0#\x0e\x04\x0e\x08\0>\0\n"
6687         "\0]\0>\0<\0d\0/\0>";
6688 
6689     if (_XML_Parse_SINGLE_BYTES(parser, text, sizeof(text)-1,
6690                                 XML_TRUE) != XML_STATUS_ERROR)
6691         fail("Invalid UTF16 attribute keyword not faulted");
6692     if (XML_GetErrorCode(parser) != XML_ERROR_SYNTAX)
6693         xml_failure(parser);
6694 }
6695 END_TEST
6696 
6697 /* Test that invalid syntax in a <!DOCTYPE> is rejected.  Do this
6698  * using prefix-encoding (see above) to trigger specific code paths
6699  */
START_TEST(test_bad_doctype)6700 START_TEST(test_bad_doctype)
6701 {
6702     const char *text =
6703         "<?xml version='1.0' encoding='prefix-conv'?>\n"
6704         "<!DOCTYPE doc [ \x80\x44 ]><doc/>";
6705 
6706     XML_SetUnknownEncodingHandler(parser, MiscEncodingHandler, NULL);
6707     expect_failure(text, XML_ERROR_SYNTAX,
6708                    "Invalid bytes in DOCTYPE not faulted");
6709 }
6710 END_TEST
6711 
START_TEST(test_bad_doctype_utf16)6712 START_TEST(test_bad_doctype_utf16)
6713 {
6714     const char text[] =
6715         /* <!DOCTYPE doc [ \x06f2 ]><doc/>
6716          *
6717          * U+06F2 = EXTENDED ARABIC-INDIC DIGIT TWO, a valid number
6718          * (name character) but not a valid letter (name start character)
6719          */
6720         "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0 "
6721         "\x06\xf2"
6722         "\0 \0]\0>\0<\0d\0o\0c\0/\0>";
6723 
6724     if (_XML_Parse_SINGLE_BYTES(parser, text, sizeof(text)-1,
6725                                 XML_TRUE) != XML_STATUS_ERROR)
6726         fail("Invalid bytes in DOCTYPE not faulted");
6727     if (XML_GetErrorCode(parser) != XML_ERROR_SYNTAX)
6728         xml_failure(parser);
6729 }
6730 END_TEST
6731 
START_TEST(test_bad_doctype_plus)6732 START_TEST(test_bad_doctype_plus)
6733 {
6734     const char *text =
6735         "<!DOCTYPE 1+ [ <!ENTITY foo 'bar'> ]>\n"
6736         "<1+>&foo;</1+>";
6737 
6738     expect_failure(text, XML_ERROR_INVALID_TOKEN,
6739                    "'+' in document name not faulted");
6740 }
6741 END_TEST
6742 
START_TEST(test_bad_doctype_star)6743 START_TEST(test_bad_doctype_star)
6744 {
6745     const char *text =
6746         "<!DOCTYPE 1* [ <!ENTITY foo 'bar'> ]>\n"
6747         "<1*>&foo;</1*>";
6748 
6749     expect_failure(text, XML_ERROR_INVALID_TOKEN,
6750                    "'*' in document name not faulted");
6751 }
6752 END_TEST
6753 
START_TEST(test_bad_doctype_query)6754 START_TEST(test_bad_doctype_query)
6755 {
6756     const char *text =
6757         "<!DOCTYPE 1? [ <!ENTITY foo 'bar'> ]>\n"
6758         "<1?>&foo;</1?>";
6759 
6760     expect_failure(text, XML_ERROR_INVALID_TOKEN,
6761                    "'?' in document name not faulted");
6762 }
6763 END_TEST
6764 
START_TEST(test_unknown_encoding_bad_ignore)6765 START_TEST(test_unknown_encoding_bad_ignore)
6766 {
6767     const char *text =
6768         "<?xml version='1.0' encoding='prefix-conv'?>"
6769         "<!DOCTYPE doc SYSTEM 'foo'>"
6770         "<doc><e>&entity;</e></doc>";
6771     ExtFaults fault = {
6772         "<![IGNORE[<!ELEMENT \xffG (#PCDATA)*>]]>",
6773         "Invalid character not faulted",
6774         XCS("prefix-conv"),
6775         XML_ERROR_INVALID_TOKEN
6776     };
6777 
6778     XML_SetUnknownEncodingHandler(parser, MiscEncodingHandler, NULL);
6779     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6780     XML_SetExternalEntityRefHandler(parser, external_entity_faulter);
6781     XML_SetUserData(parser, &fault);
6782     expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
6783                    "Bad IGNORE section with unknown encoding not failed");
6784 }
6785 END_TEST
6786 
START_TEST(test_entity_in_utf16_be_attr)6787 START_TEST(test_entity_in_utf16_be_attr)
6788 {
6789     const char text[] =
6790         /* <e a='&#228; &#x00E4;'></e> */
6791         "\0<\0e\0 \0a\0=\0'\0&\0#\0\x32\0\x32\0\x38\0;\0 "
6792         "\0&\0#\0x\0\x30\0\x30\0E\0\x34\0;\0'\0>\0<\0/\0e\0>";
6793 #ifdef XML_UNICODE
6794     const XML_Char *expected = XCS("\x00e4 \x00e4");
6795 #else
6796     const XML_Char *expected = XCS("\xc3\xa4 \xc3\xa4");
6797 #endif
6798     CharData storage;
6799 
6800     CharData_Init(&storage);
6801     XML_SetUserData(parser, &storage);
6802     XML_SetStartElementHandler(parser, accumulate_attribute);
6803     if (_XML_Parse_SINGLE_BYTES(parser, text, sizeof(text)-1,
6804                                 XML_TRUE) == XML_STATUS_ERROR)
6805         xml_failure(parser);
6806     CharData_CheckXMLChars(&storage, expected);
6807 }
6808 END_TEST
6809 
START_TEST(test_entity_in_utf16_le_attr)6810 START_TEST(test_entity_in_utf16_le_attr)
6811 {
6812     const char text[] =
6813         /* <e a='&#228; &#x00E4;'></e> */
6814         "<\0e\0 \0a\0=\0'\0&\0#\0\x32\0\x32\0\x38\0;\0 \0"
6815         "&\0#\0x\0\x30\0\x30\0E\0\x34\0;\0'\0>\0<\0/\0e\0>\0";
6816 #ifdef XML_UNICODE
6817     const XML_Char *expected = XCS("\x00e4 \x00e4");
6818 #else
6819     const XML_Char *expected = XCS("\xc3\xa4 \xc3\xa4");
6820 #endif
6821     CharData storage;
6822 
6823     CharData_Init(&storage);
6824     XML_SetUserData(parser, &storage);
6825     XML_SetStartElementHandler(parser, accumulate_attribute);
6826     if (_XML_Parse_SINGLE_BYTES(parser, text, sizeof(text)-1,
6827                                 XML_TRUE) == XML_STATUS_ERROR)
6828         xml_failure(parser);
6829     CharData_CheckXMLChars(&storage, expected);
6830 }
6831 END_TEST
6832 
START_TEST(test_entity_public_utf16_be)6833 START_TEST(test_entity_public_utf16_be)
6834 {
6835     const char text[] =
6836         /* <!DOCTYPE d [ */
6837         "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n"
6838         /* <!ENTITY % e PUBLIC 'foo' 'bar.ent'> */
6839         "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \0e\0 \0P\0U\0B\0L\0I\0C\0 "
6840         "\0'\0f\0o\0o\0'\0 \0'\0b\0a\0r\0.\0e\0n\0t\0'\0>\0\n"
6841         /* %e; */
6842         "\0%\0e\0;\0\n"
6843         /* ]> */
6844         "\0]\0>\0\n"
6845         /* <d>&j;</d> */
6846         "\0<\0d\0>\0&\0j\0;\0<\0/\0d\0>";
6847     ExtTest2 test_data = {
6848         /* <!ENTITY j 'baz'> */
6849         "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0j\0 \0'\0b\0a\0z\0'\0>",
6850         34,
6851         NULL,
6852         NULL,
6853         EE_PARSE_NONE
6854     };
6855     const XML_Char *expected = XCS("baz");
6856     CharData storage;
6857 
6858     CharData_Init(&storage);
6859     test_data.storage = &storage;
6860     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6861     XML_SetExternalEntityRefHandler(parser, external_entity_loader2);
6862     XML_SetUserData(parser, &test_data);
6863     XML_SetCharacterDataHandler(parser, ext2_accumulate_characters);
6864     if (_XML_Parse_SINGLE_BYTES(parser, text, sizeof(text)-1,
6865                                 XML_TRUE) == XML_STATUS_ERROR)
6866         xml_failure(parser);
6867     CharData_CheckXMLChars(&storage, expected);
6868 }
6869 END_TEST
6870 
START_TEST(test_entity_public_utf16_le)6871 START_TEST(test_entity_public_utf16_le)
6872 {
6873     const char text[] =
6874         /* <!DOCTYPE d [ */
6875         "<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n\0"
6876         /* <!ENTITY % e PUBLIC 'foo' 'bar.ent'> */
6877         "<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \0e\0 \0P\0U\0B\0L\0I\0C\0 \0"
6878         "'\0f\0o\0o\0'\0 \0'\0b\0a\0r\0.\0e\0n\0t\0'\0>\0\n\0"
6879         /* %e; */
6880         "%\0e\0;\0\n\0"
6881         /* ]> */
6882         "]\0>\0\n\0"
6883         /* <d>&j;</d> */
6884         "<\0d\0>\0&\0j\0;\0<\0/\0d\0>\0";
6885     ExtTest2 test_data = {
6886         /* <!ENTITY j 'baz'> */
6887         "<\0!\0E\0N\0T\0I\0T\0Y\0 \0j\0 \0'\0b\0a\0z\0'\0>\0",
6888         34,
6889         NULL,
6890         NULL,
6891         EE_PARSE_NONE
6892     };
6893     const XML_Char *expected = XCS("baz");
6894     CharData storage;
6895 
6896     CharData_Init(&storage);
6897     test_data.storage = &storage;
6898     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6899     XML_SetExternalEntityRefHandler(parser, external_entity_loader2);
6900     XML_SetUserData(parser, &test_data);
6901     XML_SetCharacterDataHandler(parser, ext2_accumulate_characters);
6902     if (_XML_Parse_SINGLE_BYTES(parser, text, sizeof(text)-1,
6903                                 XML_TRUE) == XML_STATUS_ERROR)
6904         xml_failure(parser);
6905     CharData_CheckXMLChars(&storage, expected);
6906 }
6907 END_TEST
6908 
6909 /* Test that a doctype with neither an internal nor external subset is
6910  * faulted
6911  */
START_TEST(test_short_doctype)6912 START_TEST(test_short_doctype)
6913 {
6914     const char *text = "<!DOCTYPE doc></doc>";
6915     expect_failure(text, XML_ERROR_INVALID_TOKEN,
6916                    "DOCTYPE without subset not rejected");
6917 }
6918 END_TEST
6919 
START_TEST(test_short_doctype_2)6920 START_TEST(test_short_doctype_2)
6921 {
6922     const char *text = "<!DOCTYPE doc PUBLIC></doc>";
6923     expect_failure(text, XML_ERROR_SYNTAX,
6924                    "DOCTYPE without Public ID not rejected");
6925 }
6926 END_TEST
6927 
START_TEST(test_short_doctype_3)6928 START_TEST(test_short_doctype_3)
6929 {
6930     const char *text = "<!DOCTYPE doc SYSTEM></doc>";
6931     expect_failure(text, XML_ERROR_SYNTAX,
6932                    "DOCTYPE without System ID not rejected");
6933 }
6934 END_TEST
6935 
START_TEST(test_long_doctype)6936 START_TEST(test_long_doctype)
6937 {
6938     const char *text = "<!DOCTYPE doc PUBLIC 'foo' 'bar' 'baz'></doc>";
6939     expect_failure(text, XML_ERROR_SYNTAX,
6940                    "DOCTYPE with extra ID not rejected");
6941 }
6942 END_TEST
6943 
START_TEST(test_bad_entity)6944 START_TEST(test_bad_entity)
6945 {
6946     const char *text =
6947         "<!DOCTYPE doc [\n"
6948         "  <!ENTITY foo PUBLIC>\n"
6949         "]>\n"
6950         "<doc/>";
6951     expect_failure(text, XML_ERROR_SYNTAX,
6952                    "ENTITY without Public ID is not rejected");
6953 }
6954 END_TEST
6955 
6956 /* Test unquoted value is faulted */
START_TEST(test_bad_entity_2)6957 START_TEST(test_bad_entity_2)
6958 {
6959     const char *text =
6960         "<!DOCTYPE doc [\n"
6961         "  <!ENTITY % foo bar>\n"
6962         "]>\n"
6963         "<doc/>";
6964     expect_failure(text, XML_ERROR_SYNTAX,
6965                    "ENTITY without Public ID is not rejected");
6966 }
6967 END_TEST
6968 
START_TEST(test_bad_entity_3)6969 START_TEST(test_bad_entity_3)
6970 {
6971     const char *text =
6972         "<!DOCTYPE doc [\n"
6973         "  <!ENTITY % foo PUBLIC>\n"
6974         "]>\n"
6975         "<doc/>";
6976     expect_failure(text, XML_ERROR_SYNTAX,
6977                    "Parameter ENTITY without Public ID is not rejected");
6978 }
6979 END_TEST
6980 
START_TEST(test_bad_entity_4)6981 START_TEST(test_bad_entity_4)
6982 {
6983     const char *text =
6984         "<!DOCTYPE doc [\n"
6985         "  <!ENTITY % foo SYSTEM>\n"
6986         "]>\n"
6987         "<doc/>";
6988     expect_failure(text, XML_ERROR_SYNTAX,
6989                    "Parameter ENTITY without Public ID is not rejected");
6990 }
6991 END_TEST
6992 
START_TEST(test_bad_notation)6993 START_TEST(test_bad_notation)
6994 {
6995     const char *text =
6996         "<!DOCTYPE doc [\n"
6997         "  <!NOTATION n SYSTEM>\n"
6998         "]>\n"
6999         "<doc/>";
7000     expect_failure(text, XML_ERROR_SYNTAX,
7001                    "Notation without System ID is not rejected");
7002 }
7003 END_TEST
7004 
7005 /* Test for issue #11, wrongly suppressed default handler */
7006 typedef struct default_check {
7007     const XML_Char *expected;
7008     const int expectedLen;
7009     XML_Bool seen;
7010 } DefaultCheck;
7011 
7012 static void XMLCALL
checking_default_handler(void * userData,const XML_Char * s,int len)7013 checking_default_handler(void *userData,
7014                          const XML_Char *s,
7015                          int len)
7016 {
7017     DefaultCheck *data = (DefaultCheck *)userData;
7018     int i;
7019 
7020     for (i = 0; data[i].expected != NULL; i++) {
7021         if (data[i].expectedLen == len &&
7022             !memcmp(data[i].expected, s, len * sizeof(XML_Char))) {
7023             data[i].seen = XML_TRUE;
7024             break;
7025         }
7026     }
7027 }
7028 
START_TEST(test_default_doctype_handler)7029 START_TEST(test_default_doctype_handler)
7030 {
7031     const char *text =
7032         "<!DOCTYPE doc PUBLIC 'pubname' 'test.dtd' [\n"
7033         "  <!ENTITY foo 'bar'>\n"
7034         "]>\n"
7035         "<doc>&foo;</doc>";
7036     DefaultCheck test_data[] = {
7037         {
7038             XCS("'pubname'"),
7039             9,
7040             XML_FALSE
7041         },
7042         {
7043             XCS("'test.dtd'"),
7044             10,
7045             XML_FALSE
7046         },
7047         { NULL, 0, XML_FALSE }
7048     };
7049     int i;
7050 
7051     XML_SetUserData(parser, &test_data);
7052     XML_SetDefaultHandler(parser, checking_default_handler);
7053     XML_SetEntityDeclHandler(parser, dummy_entity_decl_handler);
7054     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
7055                                 XML_TRUE) == XML_STATUS_ERROR)
7056         xml_failure(parser);
7057     for (i = 0; test_data[i].expected != NULL; i++)
7058         if (!test_data[i].seen)
7059             fail("Default handler not run for public !DOCTYPE");
7060 }
7061 END_TEST
7062 
START_TEST(test_empty_element_abort)7063 START_TEST(test_empty_element_abort)
7064 {
7065     const char *text = "<abort/>";
7066 
7067     XML_SetStartElementHandler(parser, start_element_suspender);
7068     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
7069                                 XML_TRUE) != XML_STATUS_ERROR)
7070         fail("Expected to error on abort");
7071 }
7072 END_TEST
7073 
7074 /*
7075  * Namespaces tests.
7076  */
7077 
7078 static void
namespace_setup(void)7079 namespace_setup(void)
7080 {
7081     parser = XML_ParserCreateNS(NULL, XCS(' '));
7082     if (parser == NULL)
7083         fail("Parser not created.");
7084 }
7085 
7086 static void
namespace_teardown(void)7087 namespace_teardown(void)
7088 {
7089     basic_teardown();
7090 }
7091 
7092 /* Check that an element name and attribute name match the expected values.
7093    The expected values are passed as an array reference of string pointers
7094    provided as the userData argument; the first is the expected
7095    element name, and the second is the expected attribute name.
7096 */
7097 static int triplet_start_flag = XML_FALSE;
7098 static int triplet_end_flag = XML_FALSE;
7099 
7100 static void XMLCALL
triplet_start_checker(void * userData,const XML_Char * name,const XML_Char ** atts)7101 triplet_start_checker(void *userData, const XML_Char *name,
7102                       const XML_Char **atts)
7103 {
7104     XML_Char **elemstr = (XML_Char **)userData;
7105     char buffer[1024];
7106     if (xcstrcmp(elemstr[0], name) != 0) {
7107         sprintf(buffer, "unexpected start string: '%" XML_FMT_STR "'", name);
7108         fail(buffer);
7109     }
7110     if (xcstrcmp(elemstr[1], atts[0]) != 0) {
7111         sprintf(buffer, "unexpected attribute string: '%" XML_FMT_STR "'",
7112                 atts[0]);
7113         fail(buffer);
7114     }
7115     triplet_start_flag = XML_TRUE;
7116 }
7117 
7118 /* Check that the element name passed to the end-element handler matches
7119    the expected value.  The expected value is passed as the first element
7120    in an array of strings passed as the userData argument.
7121 */
7122 static void XMLCALL
triplet_end_checker(void * userData,const XML_Char * name)7123 triplet_end_checker(void *userData, const XML_Char *name)
7124 {
7125     XML_Char **elemstr = (XML_Char **)userData;
7126     if (xcstrcmp(elemstr[0], name) != 0) {
7127         char buffer[1024];
7128         sprintf(buffer, "unexpected end string: '%" XML_FMT_STR "'", name);
7129         fail(buffer);
7130     }
7131     triplet_end_flag = XML_TRUE;
7132 }
7133 
START_TEST(test_return_ns_triplet)7134 START_TEST(test_return_ns_triplet)
7135 {
7136     const char *text =
7137         "<foo:e xmlns:foo='http://example.org/' bar:a='12'\n"
7138         "       xmlns:bar='http://example.org/'>";
7139     const char *epilog = "</foo:e>";
7140     const XML_Char *elemstr[] = {
7141         XCS("http://example.org/ e foo"),
7142         XCS("http://example.org/ a bar")
7143     };
7144     XML_SetReturnNSTriplet(parser, XML_TRUE);
7145     XML_SetUserData(parser, elemstr);
7146     XML_SetElementHandler(parser, triplet_start_checker,
7147                           triplet_end_checker);
7148     XML_SetNamespaceDeclHandler(parser,
7149                                 dummy_start_namespace_decl_handler,
7150                                 dummy_end_namespace_decl_handler);
7151     triplet_start_flag = XML_FALSE;
7152     triplet_end_flag = XML_FALSE;
7153     dummy_handler_flags = 0;
7154     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
7155                                 XML_FALSE) == XML_STATUS_ERROR)
7156         xml_failure(parser);
7157     if (!triplet_start_flag)
7158         fail("triplet_start_checker not invoked");
7159     /* Check that unsetting "return triplets" fails while still parsing */
7160     XML_SetReturnNSTriplet(parser, XML_FALSE);
7161     if (_XML_Parse_SINGLE_BYTES(parser, epilog, strlen(epilog),
7162                                 XML_TRUE) == XML_STATUS_ERROR)
7163         xml_failure(parser);
7164     if (!triplet_end_flag)
7165         fail("triplet_end_checker not invoked");
7166     if (dummy_handler_flags != (DUMMY_START_NS_DECL_HANDLER_FLAG |
7167                                 DUMMY_END_NS_DECL_HANDLER_FLAG))
7168         fail("Namespace handlers not called");
7169 }
7170 END_TEST
7171 
7172 static void XMLCALL
overwrite_start_checker(void * userData,const XML_Char * name,const XML_Char ** atts)7173 overwrite_start_checker(void *userData, const XML_Char *name,
7174                         const XML_Char **atts)
7175 {
7176     CharData *storage = (CharData *) userData;
7177     CharData_AppendXMLChars(storage, XCS("start "), 6);
7178     CharData_AppendXMLChars(storage, name, -1);
7179     while (*atts != NULL) {
7180         CharData_AppendXMLChars(storage, XCS("\nattribute "), 11);
7181         CharData_AppendXMLChars(storage, *atts, -1);
7182         atts += 2;
7183     }
7184     CharData_AppendXMLChars(storage, XCS("\n"), 1);
7185 }
7186 
7187 static void XMLCALL
overwrite_end_checker(void * userData,const XML_Char * name)7188 overwrite_end_checker(void *userData, const XML_Char *name)
7189 {
7190     CharData *storage = (CharData *) userData;
7191     CharData_AppendXMLChars(storage, XCS("end "), 4);
7192     CharData_AppendXMLChars(storage, name, -1);
7193     CharData_AppendXMLChars(storage, XCS("\n"), 1);
7194 }
7195 
7196 static void
run_ns_tagname_overwrite_test(const char * text,const XML_Char * result)7197 run_ns_tagname_overwrite_test(const char *text, const XML_Char *result)
7198 {
7199     CharData storage;
7200     CharData_Init(&storage);
7201     XML_SetUserData(parser, &storage);
7202     XML_SetElementHandler(parser,
7203                           overwrite_start_checker, overwrite_end_checker);
7204     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
7205         xml_failure(parser);
7206     CharData_CheckXMLChars(&storage, result);
7207 }
7208 
7209 /* Regression test for SF bug #566334. */
START_TEST(test_ns_tagname_overwrite)7210 START_TEST(test_ns_tagname_overwrite)
7211 {
7212     const char *text =
7213         "<n:e xmlns:n='http://example.org/'>\n"
7214         "  <n:f n:attr='foo'/>\n"
7215         "  <n:g n:attr2='bar'/>\n"
7216         "</n:e>";
7217     const XML_Char *result =
7218         XCS("start http://example.org/ e\n")
7219         XCS("start http://example.org/ f\n")
7220         XCS("attribute http://example.org/ attr\n")
7221         XCS("end http://example.org/ f\n")
7222         XCS("start http://example.org/ g\n")
7223         XCS("attribute http://example.org/ attr2\n")
7224         XCS("end http://example.org/ g\n")
7225         XCS("end http://example.org/ e\n");
7226     run_ns_tagname_overwrite_test(text, result);
7227 }
7228 END_TEST
7229 
7230 /* Regression test for SF bug #566334. */
START_TEST(test_ns_tagname_overwrite_triplet)7231 START_TEST(test_ns_tagname_overwrite_triplet)
7232 {
7233     const char *text =
7234         "<n:e xmlns:n='http://example.org/'>\n"
7235         "  <n:f n:attr='foo'/>\n"
7236         "  <n:g n:attr2='bar'/>\n"
7237         "</n:e>";
7238     const XML_Char *result =
7239         XCS("start http://example.org/ e n\n")
7240         XCS("start http://example.org/ f n\n")
7241         XCS("attribute http://example.org/ attr n\n")
7242         XCS("end http://example.org/ f n\n")
7243         XCS("start http://example.org/ g n\n")
7244         XCS("attribute http://example.org/ attr2 n\n")
7245         XCS("end http://example.org/ g n\n")
7246         XCS("end http://example.org/ e n\n");
7247     XML_SetReturnNSTriplet(parser, XML_TRUE);
7248     run_ns_tagname_overwrite_test(text, result);
7249 }
7250 END_TEST
7251 
7252 
7253 /* Regression test for SF bug #620343. */
7254 static void XMLCALL
start_element_fail(void * UNUSED_P (userData),const XML_Char * UNUSED_P (name),const XML_Char ** UNUSED_P (atts))7255 start_element_fail(void *UNUSED_P(userData),
7256                    const XML_Char *UNUSED_P(name), const XML_Char **UNUSED_P(atts))
7257 {
7258     /* We should never get here. */
7259     fail("should never reach start_element_fail()");
7260 }
7261 
7262 static void XMLCALL
start_ns_clearing_start_element(void * userData,const XML_Char * UNUSED_P (prefix),const XML_Char * UNUSED_P (uri))7263 start_ns_clearing_start_element(void *userData,
7264                                 const XML_Char *UNUSED_P(prefix),
7265                                 const XML_Char *UNUSED_P(uri))
7266 {
7267     XML_SetStartElementHandler((XML_Parser) userData, NULL);
7268 }
7269 
START_TEST(test_start_ns_clears_start_element)7270 START_TEST(test_start_ns_clears_start_element)
7271 {
7272     /* This needs to use separate start/end tags; using the empty tag
7273        syntax doesn't cause the problematic path through Expat to be
7274        taken.
7275     */
7276     const char *text = "<e xmlns='http://example.org/'></e>";
7277 
7278     XML_SetStartElementHandler(parser, start_element_fail);
7279     XML_SetStartNamespaceDeclHandler(parser, start_ns_clearing_start_element);
7280     XML_SetEndNamespaceDeclHandler(parser, dummy_end_namespace_decl_handler);
7281     XML_UseParserAsHandlerArg(parser);
7282     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
7283         xml_failure(parser);
7284 }
7285 END_TEST
7286 
7287 /* Regression test for SF bug #616863. */
7288 static int XMLCALL
external_entity_handler(XML_Parser parser,const XML_Char * context,const XML_Char * UNUSED_P (base),const XML_Char * UNUSED_P (systemId),const XML_Char * UNUSED_P (publicId))7289 external_entity_handler(XML_Parser parser,
7290                         const XML_Char *context,
7291                         const XML_Char *UNUSED_P(base),
7292                         const XML_Char *UNUSED_P(systemId),
7293                         const XML_Char *UNUSED_P(publicId))
7294 {
7295     intptr_t callno = 1 + (intptr_t)XML_GetUserData(parser);
7296     const char *text;
7297     XML_Parser p2;
7298 
7299     if (callno == 1)
7300         text = ("<!ELEMENT doc (e+)>\n"
7301                 "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
7302                 "<!ELEMENT e EMPTY>\n");
7303     else
7304         text = ("<?xml version='1.0' encoding='us-ascii'?>"
7305                 "<e/>");
7306 
7307     XML_SetUserData(parser, (void *) callno);
7308     p2 = XML_ExternalEntityParserCreate(parser, context, NULL);
7309     if (_XML_Parse_SINGLE_BYTES(p2, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR) {
7310         xml_failure(p2);
7311         return XML_STATUS_ERROR;
7312     }
7313     XML_ParserFree(p2);
7314     return XML_STATUS_OK;
7315 }
7316 
START_TEST(test_default_ns_from_ext_subset_and_ext_ge)7317 START_TEST(test_default_ns_from_ext_subset_and_ext_ge)
7318 {
7319     const char *text =
7320         "<?xml version='1.0'?>\n"
7321         "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n"
7322         "  <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n"
7323         "]>\n"
7324         "<doc xmlns='http://example.org/ns1'>\n"
7325         "&en;\n"
7326         "</doc>";
7327 
7328     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
7329     XML_SetExternalEntityRefHandler(parser, external_entity_handler);
7330     /* We actually need to set this handler to tickle this bug. */
7331     XML_SetStartElementHandler(parser, dummy_start_element);
7332     XML_SetUserData(parser, NULL);
7333     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
7334         xml_failure(parser);
7335 }
7336 END_TEST
7337 
7338 /* Regression test #1 for SF bug #673791. */
START_TEST(test_ns_prefix_with_empty_uri_1)7339 START_TEST(test_ns_prefix_with_empty_uri_1)
7340 {
7341     const char *text =
7342         "<doc xmlns:prefix='http://example.org/'>\n"
7343         "  <e xmlns:prefix=''/>\n"
7344         "</doc>";
7345 
7346     expect_failure(text,
7347                    XML_ERROR_UNDECLARING_PREFIX,
7348                    "Did not report re-setting namespace"
7349                    " URI with prefix to ''.");
7350 }
7351 END_TEST
7352 
7353 /* Regression test #2 for SF bug #673791. */
START_TEST(test_ns_prefix_with_empty_uri_2)7354 START_TEST(test_ns_prefix_with_empty_uri_2)
7355 {
7356     const char *text =
7357         "<?xml version='1.0'?>\n"
7358         "<docelem xmlns:pre=''/>";
7359 
7360     expect_failure(text,
7361                    XML_ERROR_UNDECLARING_PREFIX,
7362                    "Did not report setting namespace URI with prefix to ''.");
7363 }
7364 END_TEST
7365 
7366 /* Regression test #3 for SF bug #673791. */
START_TEST(test_ns_prefix_with_empty_uri_3)7367 START_TEST(test_ns_prefix_with_empty_uri_3)
7368 {
7369     const char *text =
7370         "<!DOCTYPE doc [\n"
7371         "  <!ELEMENT doc EMPTY>\n"
7372         "  <!ATTLIST doc\n"
7373         "    xmlns:prefix CDATA ''>\n"
7374         "]>\n"
7375         "<doc/>";
7376 
7377     expect_failure(text,
7378                    XML_ERROR_UNDECLARING_PREFIX,
7379                    "Didn't report attr default setting NS w/ prefix to ''.");
7380 }
7381 END_TEST
7382 
7383 /* Regression test #4 for SF bug #673791. */
START_TEST(test_ns_prefix_with_empty_uri_4)7384 START_TEST(test_ns_prefix_with_empty_uri_4)
7385 {
7386     const char *text =
7387         "<!DOCTYPE doc [\n"
7388         "  <!ELEMENT prefix:doc EMPTY>\n"
7389         "  <!ATTLIST prefix:doc\n"
7390         "    xmlns:prefix CDATA 'http://example.org/'>\n"
7391         "]>\n"
7392         "<prefix:doc/>";
7393     /* Packaged info expected by the end element handler;
7394        the weird structuring lets us re-use the triplet_end_checker()
7395        function also used for another test. */
7396     const XML_Char *elemstr[] = {
7397         XCS("http://example.org/ doc prefix")
7398     };
7399     XML_SetReturnNSTriplet(parser, XML_TRUE);
7400     XML_SetUserData(parser, elemstr);
7401     XML_SetEndElementHandler(parser, triplet_end_checker);
7402     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
7403         xml_failure(parser);
7404 }
7405 END_TEST
7406 
7407 /* Test with non-xmlns prefix */
START_TEST(test_ns_unbound_prefix)7408 START_TEST(test_ns_unbound_prefix)
7409 {
7410     const char *text =
7411         "<!DOCTYPE doc [\n"
7412         "  <!ELEMENT prefix:doc EMPTY>\n"
7413         "  <!ATTLIST prefix:doc\n"
7414         "    notxmlns:prefix CDATA 'http://example.org/'>\n"
7415         "]>\n"
7416         "<prefix:doc/>";
7417 
7418     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
7419                                 XML_TRUE) != XML_STATUS_ERROR)
7420         fail("Unbound prefix incorrectly passed");
7421     if (XML_GetErrorCode(parser) != XML_ERROR_UNBOUND_PREFIX)
7422         xml_failure(parser);
7423 }
7424 END_TEST
7425 
START_TEST(test_ns_default_with_empty_uri)7426 START_TEST(test_ns_default_with_empty_uri)
7427 {
7428     const char *text =
7429         "<doc xmlns='http://example.org/'>\n"
7430         "  <e xmlns=''/>\n"
7431         "</doc>";
7432     /* Add some handlers to exercise extra code paths */
7433     XML_SetStartNamespaceDeclHandler(parser,
7434                                      dummy_start_namespace_decl_handler);
7435     XML_SetEndNamespaceDeclHandler(parser,
7436                                    dummy_end_namespace_decl_handler);
7437     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
7438         xml_failure(parser);
7439 }
7440 END_TEST
7441 
7442 /* Regression test for SF bug #692964: two prefixes for one namespace. */
START_TEST(test_ns_duplicate_attrs_diff_prefixes)7443 START_TEST(test_ns_duplicate_attrs_diff_prefixes)
7444 {
7445     const char *text =
7446         "<doc xmlns:a='http://example.org/a'\n"
7447         "     xmlns:b='http://example.org/a'\n"
7448         "     a:a='v' b:a='v' />";
7449     expect_failure(text,
7450                    XML_ERROR_DUPLICATE_ATTRIBUTE,
7451                    "did not report multiple attributes with same URI+name");
7452 }
7453 END_TEST
7454 
START_TEST(test_ns_duplicate_hashes)7455 START_TEST(test_ns_duplicate_hashes)
7456 {
7457     /* The hash of an attribute is calculated as the hash of its URI
7458      * concatenated with a space followed by its name (after the
7459      * colon).  We wish to generate attributes with the same hash
7460      * value modulo the attribute table size so that we can check that
7461      * the attribute hash table works correctly.  The attribute hash
7462      * table size will be the smallest power of two greater than the
7463      * number of attributes, but at least eight.  There is
7464      * unfortunately no programmatic way of getting the hash or the
7465      * table size at user level, but the test code coverage percentage
7466      * will drop if the hashes cease to point to the same row.
7467      *
7468      * The cunning plan is to have few enough attributes to have a
7469      * reliable table size of 8, and have the single letter attribute
7470      * names be 8 characters apart, producing a hash which will be the
7471      * same modulo 8.
7472      */
7473     const char *text =
7474         "<doc xmlns:a='http://example.org/a'\n"
7475         "     a:a='v' a:i='w' />";
7476     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
7477                                 XML_TRUE) == XML_STATUS_ERROR)
7478         xml_failure(parser);
7479 }
7480 END_TEST
7481 
7482 /* Regression test for SF bug #695401: unbound prefix. */
START_TEST(test_ns_unbound_prefix_on_attribute)7483 START_TEST(test_ns_unbound_prefix_on_attribute)
7484 {
7485     const char *text = "<doc a:attr=''/>";
7486     expect_failure(text,
7487                    XML_ERROR_UNBOUND_PREFIX,
7488                    "did not report unbound prefix on attribute");
7489 }
7490 END_TEST
7491 
7492 /* Regression test for SF bug #695401: unbound prefix. */
START_TEST(test_ns_unbound_prefix_on_element)7493 START_TEST(test_ns_unbound_prefix_on_element)
7494 {
7495     const char *text = "<a:doc/>";
7496     expect_failure(text,
7497                    XML_ERROR_UNBOUND_PREFIX,
7498                    "did not report unbound prefix on element");
7499 }
7500 END_TEST
7501 
7502 /* Test that the parsing status is correctly reset by XML_ParserReset().
7503  * We usE test_return_ns_triplet() for our example parse to improve
7504  * coverage of tidying up code executed.
7505  */
START_TEST(test_ns_parser_reset)7506 START_TEST(test_ns_parser_reset)
7507 {
7508     XML_ParsingStatus status;
7509 
7510     XML_GetParsingStatus(parser, &status);
7511     if (status.parsing != XML_INITIALIZED)
7512         fail("parsing status doesn't start INITIALIZED");
7513     test_return_ns_triplet();
7514     XML_GetParsingStatus(parser, &status);
7515     if (status.parsing != XML_FINISHED)
7516         fail("parsing status doesn't end FINISHED");
7517     XML_ParserReset(parser, NULL);
7518     XML_GetParsingStatus(parser, &status);
7519     if (status.parsing != XML_INITIALIZED)
7520         fail("parsing status doesn't reset to INITIALIZED");
7521 }
7522 END_TEST
7523 
7524 /* Test that long element names with namespaces are handled correctly */
START_TEST(test_ns_long_element)7525 START_TEST(test_ns_long_element)
7526 {
7527     const char *text =
7528         "<foo:thisisalongenoughelementnametotriggerareallocation\n"
7529         " xmlns:foo='http://example.org/' bar:a='12'\n"
7530         " xmlns:bar='http://example.org/'>"
7531         "</foo:thisisalongenoughelementnametotriggerareallocation>";
7532     const XML_Char *elemstr[] = {
7533         XCS("http://example.org/")
7534         XCS(" thisisalongenoughelementnametotriggerareallocation foo"),
7535         XCS("http://example.org/ a bar")
7536     };
7537 
7538     XML_SetReturnNSTriplet(parser, XML_TRUE);
7539     XML_SetUserData(parser, elemstr);
7540     XML_SetElementHandler(parser,
7541                           triplet_start_checker,
7542                           triplet_end_checker);
7543     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
7544                                 XML_TRUE) == XML_STATUS_ERROR)
7545         xml_failure(parser);
7546 }
7547 END_TEST
7548 
7549 /* Test mixed population of prefixed and unprefixed attributes */
START_TEST(test_ns_mixed_prefix_atts)7550 START_TEST(test_ns_mixed_prefix_atts)
7551 {
7552     const char *text =
7553         "<e a='12' bar:b='13'\n"
7554         " xmlns:bar='http://example.org/'>"
7555         "</e>";
7556 
7557     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
7558                                 XML_TRUE) == XML_STATUS_ERROR)
7559         xml_failure(parser);
7560 }
7561 END_TEST
7562 
7563 /* Test having a long namespaced element name inside a short one.
7564  * This exercises some internal buffer reallocation that is shared
7565  * across elements with the same namespace URI.
7566  */
START_TEST(test_ns_extend_uri_buffer)7567 START_TEST(test_ns_extend_uri_buffer)
7568 {
7569     const char *text =
7570         "<foo:e xmlns:foo='http://example.org/'>"
7571         " <foo:thisisalongenoughnametotriggerallocationaction"
7572         "   foo:a='12' />"
7573         "</foo:e>";
7574     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
7575                                 XML_TRUE) == XML_STATUS_ERROR)
7576         xml_failure(parser);
7577 }
7578 END_TEST
7579 
7580 /* Test that xmlns is correctly rejected as an attribute in the xmlns
7581  * namespace, but not in other namespaces
7582  */
START_TEST(test_ns_reserved_attributes)7583 START_TEST(test_ns_reserved_attributes)
7584 {
7585     const char *text1 =
7586         "<foo:e xmlns:foo='http://example.org/' xmlns:xmlns='12' />";
7587     const char *text2 =
7588         "<foo:e xmlns:foo='http://example.org/' foo:xmlns='12' />";
7589     expect_failure(text1, XML_ERROR_RESERVED_PREFIX_XMLNS,
7590                    "xmlns not rejected as an attribute");
7591     XML_ParserReset(parser, NULL);
7592     if (_XML_Parse_SINGLE_BYTES(parser, text2, strlen(text2),
7593                                 XML_TRUE) == XML_STATUS_ERROR)
7594         xml_failure(parser);
7595 }
7596 END_TEST
7597 
7598 /* Test more reserved attributes */
START_TEST(test_ns_reserved_attributes_2)7599 START_TEST(test_ns_reserved_attributes_2)
7600 {
7601     const char *text1 =
7602         "<foo:e xmlns:foo='http://example.org/'"
7603         "  xmlns:xml='http://example.org/' />";
7604     const char *text2 =
7605         "<foo:e xmlns:foo='http://www.w3.org/XML/1998/namespace' />";
7606     const char *text3 =
7607         "<foo:e xmlns:foo='http://www.w3.org/2000/xmlns/' />";
7608 
7609     expect_failure(text1, XML_ERROR_RESERVED_PREFIX_XML,
7610                    "xml not rejected as an attribute");
7611     XML_ParserReset(parser, NULL);
7612     expect_failure(text2, XML_ERROR_RESERVED_NAMESPACE_URI,
7613                    "Use of w3.org URL not faulted");
7614     XML_ParserReset(parser, NULL);
7615     expect_failure(text3, XML_ERROR_RESERVED_NAMESPACE_URI,
7616                    "Use of w3.org xmlns URL not faulted");
7617 }
7618 END_TEST
7619 
7620 /* Test string pool handling of namespace names of 2048 characters */
7621 /* Exercises a particular string pool growth path */
START_TEST(test_ns_extremely_long_prefix)7622 START_TEST(test_ns_extremely_long_prefix)
7623 {
7624     /* C99 compilers are only required to support 4095-character
7625      * strings, so the following needs to be split in two to be safe
7626      * for all compilers.
7627      */
7628     const char *text1 =
7629         "<doc "
7630         /* 64 character on each line */
7631         /* ...gives a total length of 2048 */
7632         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7633         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7634         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7635         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7636         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7637         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7638         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7639         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7640         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7641         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7642         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7643         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7644         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7645         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7646         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7647         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7648         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7649         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7650         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7651         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7652         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7653         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7654         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7655         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7656         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7657         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7658         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7659         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7660         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7661         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7662         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7663         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7664         ":a='12'";
7665     const char *text2 =
7666         " xmlns:"
7667         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7668         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7669         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7670         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7671         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7672         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7673         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7674         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7675         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7676         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7677         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7678         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7679         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7680         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7681         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7682         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7683         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7684         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7685         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7686         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7687         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7688         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7689         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7690         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7691         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7692         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7693         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7694         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7695         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7696         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7697         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7698         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7699         "='foo'\n>"
7700         "</doc>";
7701 
7702     if (_XML_Parse_SINGLE_BYTES(parser, text1, strlen(text1),
7703                                 XML_FALSE) == XML_STATUS_ERROR)
7704         xml_failure(parser);
7705     if (_XML_Parse_SINGLE_BYTES(parser, text2, strlen(text2),
7706                                 XML_TRUE) == XML_STATUS_ERROR)
7707         xml_failure(parser);
7708 }
7709 END_TEST
7710 
7711 /* Test unknown encoding handlers in namespace setup */
START_TEST(test_ns_unknown_encoding_success)7712 START_TEST(test_ns_unknown_encoding_success)
7713 {
7714     const char *text =
7715         "<?xml version='1.0' encoding='prefix-conv'?>\n"
7716         "<foo:e xmlns:foo='http://example.org/'>Hi</foo:e>";
7717 
7718     XML_SetUnknownEncodingHandler(parser, MiscEncodingHandler, NULL);
7719     run_character_check(text, XCS("Hi"));
7720 }
7721 END_TEST
7722 
7723 /* Test that too many colons are rejected */
START_TEST(test_ns_double_colon)7724 START_TEST(test_ns_double_colon)
7725 {
7726     const char *text =
7727         "<foo:e xmlns:foo='http://example.org/' foo:a:b='bar' />";
7728 
7729     expect_failure(text, XML_ERROR_INVALID_TOKEN,
7730                    "Double colon in attribute name not faulted");
7731 }
7732 END_TEST
7733 
START_TEST(test_ns_double_colon_element)7734 START_TEST(test_ns_double_colon_element)
7735 {
7736     const char *text =
7737         "<foo:bar:e xmlns:foo='http://example.org/' />";
7738 
7739     expect_failure(text, XML_ERROR_INVALID_TOKEN,
7740                    "Double colon in element name not faulted");
7741 }
7742 END_TEST
7743 
7744 /* Test that non-name characters after a colon are rejected */
START_TEST(test_ns_bad_attr_leafname)7745 START_TEST(test_ns_bad_attr_leafname)
7746 {
7747     const char *text =
7748         "<foo:e xmlns:foo='http://example.org/' foo:?ar='baz' />";
7749 
7750     expect_failure(text, XML_ERROR_INVALID_TOKEN,
7751                    "Invalid character in leafname not faulted");
7752 }
7753 END_TEST
7754 
START_TEST(test_ns_bad_element_leafname)7755 START_TEST(test_ns_bad_element_leafname)
7756 {
7757     const char *text =
7758         "<foo:?oc xmlns:foo='http://example.org/' />";
7759 
7760     expect_failure(text, XML_ERROR_INVALID_TOKEN,
7761                    "Invalid character in element leafname not faulted");
7762 }
7763 END_TEST
7764 
7765 /* Test high-byte-set UTF-16 characters are valid in a leafname */
START_TEST(test_ns_utf16_leafname)7766 START_TEST(test_ns_utf16_leafname)
7767 {
7768     const char text[] =
7769         /* <n:e xmlns:n='URI' n:{KHO KHWAI}='a' />
7770          * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
7771          */
7772         "<\0n\0:\0e\0 \0x\0m\0l\0n\0s\0:\0n\0=\0'\0U\0R\0I\0'\0 \0"
7773         "n\0:\0\x04\x0e=\0'\0a\0'\0 \0/\0>\0";
7774     const XML_Char *expected = XCS("a");
7775     CharData storage;
7776 
7777     CharData_Init(&storage);
7778     XML_SetStartElementHandler(parser, accumulate_attribute);
7779     XML_SetUserData(parser, &storage);
7780     if (_XML_Parse_SINGLE_BYTES(parser, text, sizeof(text)-1,
7781                                 XML_TRUE) == XML_STATUS_ERROR)
7782         xml_failure(parser);
7783     CharData_CheckXMLChars(&storage, expected);
7784 }
7785 END_TEST
7786 
START_TEST(test_ns_utf16_element_leafname)7787 START_TEST(test_ns_utf16_element_leafname)
7788 {
7789     const char text[] =
7790         /* <n:{KHO KHWAI} xmlns:n='URI'/>
7791          * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
7792          */
7793         "\0<\0n\0:\x0e\x04\0 \0x\0m\0l\0n\0s\0:\0n\0=\0'\0U\0R\0I\0'\0/\0>";
7794 #ifdef XML_UNICODE
7795     const XML_Char *expected = XCS("URI \x0e04");
7796 #else
7797     const XML_Char *expected = XCS("URI \xe0\xb8\x84");
7798 #endif
7799     CharData storage;
7800 
7801     CharData_Init(&storage);
7802     XML_SetStartElementHandler(parser, start_element_event_handler);
7803     XML_SetUserData(parser, &storage);
7804     if (_XML_Parse_SINGLE_BYTES(parser, text, sizeof(text)-1,
7805                                 XML_TRUE) == XML_STATUS_ERROR)
7806         xml_failure(parser);
7807     CharData_CheckXMLChars(&storage, expected);
7808 }
7809 END_TEST
7810 
START_TEST(test_ns_utf16_doctype)7811 START_TEST(test_ns_utf16_doctype)
7812 {
7813     const char text[] =
7814         /* <!DOCTYPE foo:{KHO KHWAI} [ <!ENTITY bar 'baz'> ]>\n
7815          * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
7816          */
7817         "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0f\0o\0o\0:\x0e\x04\0 "
7818         "\0[\0 \0<\0!\0E\0N\0T\0I\0T\0Y\0 \0b\0a\0r\0 \0'\0b\0a\0z\0'\0>\0 "
7819         "\0]\0>\0\n"
7820         /* <foo:{KHO KHWAI} xmlns:foo='URI'>&bar;</foo:{KHO KHWAI}> */
7821         "\0<\0f\0o\0o\0:\x0e\x04\0 "
7822         "\0x\0m\0l\0n\0s\0:\0f\0o\0o\0=\0'\0U\0R\0I\0'\0>"
7823         "\0&\0b\0a\0r\0;"
7824         "\0<\0/\0f\0o\0o\0:\x0e\x04\0>";
7825 #ifdef XML_UNICODE
7826     const XML_Char *expected = XCS("URI \x0e04");
7827 #else
7828     const XML_Char *expected = XCS("URI \xe0\xb8\x84");
7829 #endif
7830     CharData storage;
7831 
7832     CharData_Init(&storage);
7833     XML_SetUserData(parser, &storage);
7834     XML_SetStartElementHandler(parser, start_element_event_handler);
7835     XML_SetUnknownEncodingHandler(parser, MiscEncodingHandler, NULL);
7836     if (_XML_Parse_SINGLE_BYTES(parser, text, sizeof(text)-1,
7837                                 XML_TRUE) == XML_STATUS_ERROR)
7838         xml_failure(parser);
7839     CharData_CheckXMLChars(&storage, expected);
7840 }
7841 END_TEST
7842 
START_TEST(test_ns_invalid_doctype)7843 START_TEST(test_ns_invalid_doctype)
7844 {
7845     const char *text =
7846         "<!DOCTYPE foo:!bad [ <!ENTITY bar 'baz' ]>\n"
7847         "<foo:!bad>&bar;</foo:!bad>";
7848 
7849     expect_failure(text, XML_ERROR_INVALID_TOKEN,
7850                    "Invalid character in document local name not faulted");
7851 }
7852 END_TEST
7853 
START_TEST(test_ns_double_colon_doctype)7854 START_TEST(test_ns_double_colon_doctype)
7855 {
7856     const char *text =
7857         "<!DOCTYPE foo:a:doc [ <!ENTITY bar 'baz' ]>\n"
7858         "<foo:a:doc>&bar;</foo:a:doc>";
7859 
7860     expect_failure(text, XML_ERROR_SYNTAX,
7861                    "Double colon in document name not faulted");
7862 }
7863 END_TEST
7864 
7865 /* Control variable; the number of times duff_allocator() will successfully allocate */
7866 #define ALLOC_ALWAYS_SUCCEED (-1)
7867 #define REALLOC_ALWAYS_SUCCEED (-1)
7868 
7869 static int allocation_count = ALLOC_ALWAYS_SUCCEED;
7870 static int reallocation_count = REALLOC_ALWAYS_SUCCEED;
7871 
7872 /* Crocked allocator for allocation failure tests */
duff_allocator(size_t size)7873 static void *duff_allocator(size_t size)
7874 {
7875     if (allocation_count == 0)
7876         return NULL;
7877     if (allocation_count != ALLOC_ALWAYS_SUCCEED)
7878         allocation_count--;
7879     return malloc(size);
7880 }
7881 
7882 /* Crocked reallocator for allocation failure tests */
duff_reallocator(void * ptr,size_t size)7883 static void *duff_reallocator(void *ptr, size_t size)
7884 {
7885     if (reallocation_count == 0)
7886         return NULL;
7887     if (reallocation_count != REALLOC_ALWAYS_SUCCEED)
7888         reallocation_count--;
7889     return realloc(ptr, size);
7890 }
7891 
7892 /* Test that a failure to allocate the parser structure fails gracefully */
START_TEST(test_misc_alloc_create_parser)7893 START_TEST(test_misc_alloc_create_parser)
7894 {
7895     XML_Memory_Handling_Suite memsuite = { duff_allocator, realloc, free };
7896     unsigned int i;
7897     const unsigned int max_alloc_count = 10;
7898 
7899     /* Something this simple shouldn't need more than 10 allocations */
7900     for (i = 0; i < max_alloc_count; i++)
7901     {
7902         allocation_count = i;
7903         parser = XML_ParserCreate_MM(NULL, &memsuite, NULL);
7904         if (parser != NULL)
7905             break;
7906     }
7907     if (i == 0)
7908         fail("Parser unexpectedly ignored failing allocator");
7909     else if (i == max_alloc_count)
7910         fail("Parser not created with max allocation count");
7911 }
7912 END_TEST
7913 
7914 /* Test memory allocation failures for a parser with an encoding */
START_TEST(test_misc_alloc_create_parser_with_encoding)7915 START_TEST(test_misc_alloc_create_parser_with_encoding)
7916 {
7917     XML_Memory_Handling_Suite memsuite = { duff_allocator, realloc, free };
7918     unsigned int i;
7919     const unsigned int max_alloc_count = 10;
7920 
7921     /* Try several levels of allocation */
7922     for (i = 0; i < max_alloc_count; i++) {
7923         allocation_count = i;
7924         parser = XML_ParserCreate_MM(XCS("us-ascii"), &memsuite, NULL);
7925         if (parser != NULL)
7926             break;
7927     }
7928     if (i == 0)
7929         fail("Parser ignored failing allocator");
7930     else if (i == max_alloc_count)
7931         fail("Parser not created with max allocation count");
7932 }
7933 END_TEST
7934 
7935 /* Test that freeing a NULL parser doesn't cause an explosion.
7936  * (Not actually tested anywhere else)
7937  */
START_TEST(test_misc_null_parser)7938 START_TEST(test_misc_null_parser)
7939 {
7940     XML_ParserFree(NULL);
7941 }
7942 END_TEST
7943 
7944 /* Test that XML_ErrorString rejects out-of-range codes */
START_TEST(test_misc_error_string)7945 START_TEST(test_misc_error_string)
7946 {
7947     if (XML_ErrorString((enum XML_Error)-1) != NULL)
7948         fail("Negative error code not rejected");
7949     if (XML_ErrorString((enum XML_Error)100) != NULL)
7950         fail("Large error code not rejected");
7951 }
7952 END_TEST
7953 
7954 /* Test the version information is consistent */
7955 
7956 /* Since we are working in XML_LChars (potentially 16-bits), we
7957  * can't use the standard C library functions for character
7958  * manipulation and have to roll our own.
7959  */
7960 static int
parse_version(const XML_LChar * version_text,XML_Expat_Version * version_struct)7961 parse_version(const XML_LChar *version_text,
7962               XML_Expat_Version *version_struct)
7963 {
7964     while (*version_text != 0x00) {
7965         if (*version_text >= ASCII_0 && *version_text <= ASCII_9)
7966             break;
7967         version_text++;
7968     }
7969     if (*version_text == 0x00)
7970         return XML_FALSE;
7971 
7972     /* version_struct->major = strtoul(version_text, 10, &version_text) */
7973     version_struct->major = 0;
7974     while (*version_text >= ASCII_0 && *version_text <= ASCII_9) {
7975         version_struct->major =
7976             10 * version_struct->major + (*version_text++ - ASCII_0);
7977     }
7978     if (*version_text++ != ASCII_PERIOD)
7979         return XML_FALSE;
7980 
7981     /* Now for the minor version number */
7982     version_struct->minor = 0;
7983     while (*version_text >= ASCII_0 && *version_text <= ASCII_9) {
7984         version_struct->minor =
7985             10 * version_struct->minor + (*version_text++ - ASCII_0);
7986     }
7987     if (*version_text++ != ASCII_PERIOD)
7988         return XML_FALSE;
7989 
7990     /* Finally the micro version number */
7991     version_struct->micro = 0;
7992     while (*version_text >= ASCII_0 && *version_text <= ASCII_9) {
7993         version_struct->micro =
7994             10 * version_struct->micro + (*version_text++ - ASCII_0);
7995     }
7996     if (*version_text != 0x00)
7997         return XML_FALSE;
7998     return XML_TRUE;
7999 }
8000 
8001 static int
versions_equal(const XML_Expat_Version * first,const XML_Expat_Version * second)8002 versions_equal(const XML_Expat_Version *first,
8003                const XML_Expat_Version *second)
8004 {
8005     return (first->major == second->major &&
8006             first->minor == second->minor &&
8007             first->micro == second->micro);
8008 }
8009 
START_TEST(test_misc_version)8010 START_TEST(test_misc_version)
8011 {
8012     XML_Expat_Version read_version = XML_ExpatVersionInfo();
8013      /* Silence compiler warning with the following assignment */
8014     XML_Expat_Version parsed_version = { 0, 0, 0 };
8015     const XML_LChar *version_text = XML_ExpatVersion();
8016 
8017     if (version_text == NULL)
8018         fail("Could not obtain version text");
8019     if (!parse_version(version_text, &parsed_version))
8020         fail("Unable to parse version text");
8021     if (!versions_equal(&read_version, &parsed_version))
8022         fail("Version mismatch");
8023 
8024 #if ! defined(XML_UNICODE) || defined(XML_UNICODE_WCHAR_T)
8025     if (xcstrcmp(version_text, XCS("expat_2.2.5")))  /* needs bump on releases */
8026         fail("XML_*_VERSION in expat.h out of sync?\n");
8027 #else
8028     /* If we have XML_UNICODE defined but not XML_UNICODE_WCHAR_T
8029      * then XML_LChar is defined as char, for some reason.
8030      */
8031     if (strcmp(version_text, "expat_2.2.5")) /* needs bump on releases */
8032         fail("XML_*_VERSION in expat.h out of sync?\n");
8033 #endif  /* ! defined(XML_UNICODE) || defined(XML_UNICODE_WCHAR_T) */
8034 }
8035 END_TEST
8036 
8037 /* Test feature information */
START_TEST(test_misc_features)8038 START_TEST(test_misc_features)
8039 {
8040     const XML_Feature *features = XML_GetFeatureList();
8041 
8042     /* Prevent problems with double-freeing parsers */
8043     parser = NULL;
8044     if (features == NULL)
8045         fail("Failed to get feature information");
8046     /* Loop through the features checking what we can */
8047     while (features->feature != XML_FEATURE_END) {
8048         switch(features->feature) {
8049             case XML_FEATURE_SIZEOF_XML_CHAR:
8050                 if (features->value != sizeof(XML_Char))
8051                     fail("Incorrect size of XML_Char");
8052                 break;
8053             case XML_FEATURE_SIZEOF_XML_LCHAR:
8054                 if (features->value != sizeof(XML_LChar))
8055                     fail("Incorrect size of XML_LChar");
8056                 break;
8057             default:
8058                 break;
8059         }
8060         features++;
8061     }
8062 }
8063 END_TEST
8064 
8065 /* Regression test for GitHub Issue #17: memory leak parsing attribute
8066  * values with mixed bound and unbound namespaces.
8067  */
START_TEST(test_misc_attribute_leak)8068 START_TEST(test_misc_attribute_leak)
8069 {
8070     const char *text = "<D xmlns:L=\"D\" l:a='' L:a=''/>";
8071     XML_Memory_Handling_Suite memsuite = {
8072         tracking_malloc,
8073         tracking_realloc,
8074         tracking_free
8075     };
8076 
8077     parser = XML_ParserCreate_MM(XCS("UTF-8"), &memsuite, XCS("\n"));
8078     expect_failure(text, XML_ERROR_UNBOUND_PREFIX,
8079                    "Unbound prefixes not found");
8080     XML_ParserFree(parser);
8081     /* Prevent the teardown trying to double free */
8082     parser = NULL;
8083 
8084     if (!tracking_report())
8085         fail("Memory leak found");
8086 }
8087 END_TEST
8088 
8089 /* Test parser created for UTF-16LE is successful */
START_TEST(test_misc_utf16le)8090 START_TEST(test_misc_utf16le)
8091 {
8092     const char text[] =
8093         /* <?xml version='1.0'?><q>Hi</q> */
8094         "<\0?\0x\0m\0l\0 \0"
8095         "v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0?\0>\0"
8096         "<\0q\0>\0H\0i\0<\0/\0q\0>\0";
8097     const XML_Char *expected = XCS("Hi");
8098     CharData storage;
8099 
8100     parser = XML_ParserCreate(XCS("UTF-16LE"));
8101     if (parser == NULL)
8102         fail("Parser not created");
8103 
8104     CharData_Init(&storage);
8105     XML_SetUserData(parser, &storage);
8106     XML_SetCharacterDataHandler(parser, accumulate_characters);
8107     if (_XML_Parse_SINGLE_BYTES(parser, text, sizeof(text)-1,
8108                                 XML_TRUE) == XML_STATUS_ERROR)
8109         xml_failure(parser);
8110     CharData_CheckXMLChars(&storage, expected);
8111 }
8112 END_TEST
8113 
8114 
8115 static void
alloc_setup(void)8116 alloc_setup(void)
8117 {
8118     XML_Memory_Handling_Suite memsuite = {
8119         duff_allocator,
8120         duff_reallocator,
8121         free
8122     };
8123 
8124     /* Ensure the parser creation will go through */
8125     allocation_count = ALLOC_ALWAYS_SUCCEED;
8126     reallocation_count = REALLOC_ALWAYS_SUCCEED;
8127     parser = XML_ParserCreate_MM(NULL, &memsuite, NULL);
8128     if (parser == NULL)
8129         fail("Parser not created");
8130 }
8131 
8132 static void
alloc_teardown(void)8133 alloc_teardown(void)
8134 {
8135     basic_teardown();
8136 }
8137 
8138 
8139 /* Test the effects of allocation failures on xml declaration processing */
START_TEST(test_alloc_parse_xdecl)8140 START_TEST(test_alloc_parse_xdecl)
8141 {
8142     const char *text =
8143         "<?xml version='1.0' encoding='utf-8'?>\n"
8144         "<doc>Hello, world</doc>";
8145     int i;
8146     const int max_alloc_count = 15;
8147 
8148     for (i = 0; i < max_alloc_count; i++) {
8149         allocation_count = i;
8150         XML_SetXmlDeclHandler(parser, dummy_xdecl_handler);
8151         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
8152                                     XML_TRUE) != XML_STATUS_ERROR)
8153             break;
8154         /* Resetting the parser is insufficient, because some memory
8155          * allocations are cached within the parser.  Instead we use
8156          * the teardown and setup routines to ensure that we have the
8157          * right sort of parser back in our hands.
8158          */
8159         alloc_teardown();
8160         alloc_setup();
8161     }
8162     if (i == 0)
8163         fail("Parse succeeded despite failing allocator");
8164     if (i == max_alloc_count)
8165         fail("Parse failed with max allocations");
8166 }
8167 END_TEST
8168 
8169 /* As above, but with an encoding big enough to cause storing the
8170  * version information to expand the string pool being used.
8171  */
8172 static int XMLCALL
long_encoding_handler(void * UNUSED_P (userData),const XML_Char * UNUSED_P (encoding),XML_Encoding * info)8173 long_encoding_handler(void *UNUSED_P(userData),
8174                       const XML_Char *UNUSED_P(encoding),
8175                       XML_Encoding *info)
8176 {
8177     int i;
8178 
8179     for (i = 0; i < 256; i++)
8180         info->map[i] = i;
8181     info->data = NULL;
8182     info->convert = NULL;
8183     info->release = NULL;
8184     return XML_STATUS_OK;
8185 }
8186 
START_TEST(test_alloc_parse_xdecl_2)8187 START_TEST(test_alloc_parse_xdecl_2)
8188 {
8189     const char *text =
8190         "<?xml version='1.0' encoding='"
8191         /* Each line is 64 characters */
8192         "ThisIsAStupidlyLongEncodingNameIntendedToTriggerPoolGrowth123456"
8193         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8194         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8195         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8196         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8197         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8198         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8199         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8200         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8201         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8202         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8203         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8204         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8205         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8206         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8207         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN"
8208         "'?>"
8209         "<doc>Hello, world</doc>";
8210     int i;
8211     const int max_alloc_count = 20;
8212 
8213     for (i = 0; i < max_alloc_count; i++) {
8214         allocation_count = i;
8215         XML_SetXmlDeclHandler(parser, dummy_xdecl_handler);
8216         XML_SetUnknownEncodingHandler(parser, long_encoding_handler, NULL);
8217         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
8218                                     XML_TRUE) != XML_STATUS_ERROR)
8219             break;
8220         /* See comment in test_alloc_parse_xdecl() */
8221         alloc_teardown();
8222         alloc_setup();
8223     }
8224     if (i == 0)
8225         fail("Parse succeeded despite failing allocator");
8226     if (i == max_alloc_count)
8227         fail("Parse failed with max allocations");
8228 }
8229 END_TEST
8230 
8231 /* Test the effects of allocation failures on a straightforward parse */
START_TEST(test_alloc_parse_pi)8232 START_TEST(test_alloc_parse_pi)
8233 {
8234     const char *text =
8235         "<?xml version='1.0' encoding='utf-8'?>\n"
8236         "<?pi unknown?>\n"
8237         "<doc>"
8238         "Hello, world"
8239         "</doc>";
8240     int i;
8241     const int max_alloc_count = 15;
8242 
8243     for (i = 0; i < max_alloc_count; i++) {
8244         allocation_count = i;
8245         XML_SetProcessingInstructionHandler(parser, dummy_pi_handler);
8246         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
8247                                     XML_TRUE) != XML_STATUS_ERROR)
8248             break;
8249         /* See comment in test_alloc_parse_xdecl() */
8250         alloc_teardown();
8251         alloc_setup();
8252     }
8253     if (i == 0)
8254         fail("Parse succeeded despite failing allocator");
8255     if (i == max_alloc_count)
8256         fail("Parse failed with max allocations");
8257 }
8258 END_TEST
8259 
START_TEST(test_alloc_parse_pi_2)8260 START_TEST(test_alloc_parse_pi_2)
8261 {
8262     const char *text =
8263         "<?xml version='1.0' encoding='utf-8'?>\n"
8264         "<doc>"
8265         "Hello, world"
8266         "<?pi unknown?>\n"
8267         "</doc>";
8268     int i;
8269     const int max_alloc_count = 15;
8270 
8271     for (i = 0; i < max_alloc_count; i++) {
8272         allocation_count = i;
8273         XML_SetProcessingInstructionHandler(parser, dummy_pi_handler);
8274         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
8275                                     XML_TRUE) != XML_STATUS_ERROR)
8276             break;
8277         /* See comment in test_alloc_parse_xdecl() */
8278         alloc_teardown();
8279         alloc_setup();
8280     }
8281     if (i == 0)
8282         fail("Parse succeeded despite failing allocator");
8283     if (i == max_alloc_count)
8284         fail("Parse failed with max allocations");
8285 }
8286 END_TEST
8287 
START_TEST(test_alloc_parse_pi_3)8288 START_TEST(test_alloc_parse_pi_3)
8289 {
8290     const char *text =
8291         "<?"
8292         /* 64 characters per line */
8293         "This processing instruction should be long enough to ensure that"
8294         "it triggers the growth of an internal string pool when the      "
8295         "allocator fails at a cruicial moment FGHIJKLMNOPABCDEFGHIJKLMNOP"
8296         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8297         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8298         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8299         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8300         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8301         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8302         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8303         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8304         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8305         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8306         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8307         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8308         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8309         "Q?><doc/>";
8310     int i;
8311     const int max_alloc_count = 20;
8312 
8313     for (i = 0; i < max_alloc_count; i++) {
8314         allocation_count = i;
8315         XML_SetProcessingInstructionHandler(parser, dummy_pi_handler);
8316         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
8317                                     XML_TRUE) != XML_STATUS_ERROR)
8318             break;
8319         /* See comment in test_alloc_parse_xdecl() */
8320         alloc_teardown();
8321         alloc_setup();
8322     }
8323     if (i == 0)
8324         fail("Parse succeeded despite failing allocator");
8325     if (i == max_alloc_count)
8326         fail("Parse failed with max allocations");
8327 }
8328 END_TEST
8329 
START_TEST(test_alloc_parse_comment)8330 START_TEST(test_alloc_parse_comment)
8331 {
8332     const char *text =
8333         "<?xml version='1.0' encoding='utf-8'?>\n"
8334         "<!-- Test parsing this comment -->"
8335         "<doc>Hi</doc>";
8336     int i;
8337     const int max_alloc_count = 15;
8338 
8339     for (i = 0; i < max_alloc_count; i++) {
8340         allocation_count = i;
8341         XML_SetCommentHandler(parser, dummy_comment_handler);
8342         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
8343                                     XML_TRUE) != XML_STATUS_ERROR)
8344             break;
8345         /* See comment in test_alloc_parse_xdecl() */
8346         alloc_teardown();
8347         alloc_setup();
8348     }
8349     if (i == 0)
8350         fail("Parse succeeded despite failing allocator");
8351     if (i == max_alloc_count)
8352         fail("Parse failed with max allocations");
8353 }
8354 END_TEST
8355 
START_TEST(test_alloc_parse_comment_2)8356 START_TEST(test_alloc_parse_comment_2)
8357 {
8358     const char *text =
8359         "<?xml version='1.0' encoding='utf-8'?>\n"
8360         "<doc>"
8361         "Hello, world"
8362         "<!-- Parse this comment too -->"
8363         "</doc>";
8364     int i;
8365     const int max_alloc_count = 15;
8366 
8367     for (i = 0; i < max_alloc_count; i++) {
8368         allocation_count = i;
8369         XML_SetCommentHandler(parser, dummy_comment_handler);
8370         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
8371                                     XML_TRUE) != XML_STATUS_ERROR)
8372             break;
8373         /* See comment in test_alloc_parse_xdecl() */
8374         alloc_teardown();
8375         alloc_setup();
8376     }
8377     if (i == 0)
8378         fail("Parse succeeded despite failing allocator");
8379     if (i == max_alloc_count)
8380         fail("Parse failed with max allocations");
8381 }
8382 END_TEST
8383 
8384 static int XMLCALL
external_entity_duff_loader(XML_Parser parser,const XML_Char * context,const XML_Char * UNUSED_P (base),const XML_Char * UNUSED_P (systemId),const XML_Char * UNUSED_P (publicId))8385 external_entity_duff_loader(XML_Parser parser,
8386                             const XML_Char *context,
8387                             const XML_Char *UNUSED_P(base),
8388                             const XML_Char *UNUSED_P(systemId),
8389                             const XML_Char *UNUSED_P(publicId))
8390 {
8391     XML_Parser new_parser;
8392     unsigned int i;
8393     const unsigned int max_alloc_count = 10;
8394 
8395     /* Try a few different allocation levels */
8396     for (i = 0; i < max_alloc_count; i++)
8397     {
8398         allocation_count = i;
8399         new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8400         if (new_parser != NULL)
8401         {
8402             XML_ParserFree(new_parser);
8403             break;
8404         }
8405     }
8406     if (i == 0)
8407         fail("External parser creation ignored failing allocator");
8408     else if (i == max_alloc_count)
8409         fail("Extern parser not created with max allocation count");
8410 
8411     /* Make sure other random allocation doesn't now fail */
8412     allocation_count = ALLOC_ALWAYS_SUCCEED;
8413 
8414     /* Make sure the failure code path is executed too */
8415     return XML_STATUS_ERROR;
8416 }
8417 
8418 /* Test that external parser creation running out of memory is
8419  * correctly reported.  Based on the external entity test cases.
8420  */
START_TEST(test_alloc_create_external_parser)8421 START_TEST(test_alloc_create_external_parser)
8422 {
8423     const char *text =
8424         "<?xml version='1.0' encoding='us-ascii'?>\n"
8425         "<!DOCTYPE doc SYSTEM 'foo'>\n"
8426         "<doc>&entity;</doc>";
8427     char foo_text[] =
8428         "<!ELEMENT doc (#PCDATA)*>";
8429 
8430     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8431     XML_SetUserData(parser, foo_text);
8432     XML_SetExternalEntityRefHandler(parser,
8433                                     external_entity_duff_loader);
8434     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) != XML_STATUS_ERROR) {
8435         fail("External parser allocator returned success incorrectly");
8436     }
8437 }
8438 END_TEST
8439 
8440 /* More external parser memory allocation testing */
START_TEST(test_alloc_run_external_parser)8441 START_TEST(test_alloc_run_external_parser)
8442 {
8443     const char *text =
8444         "<?xml version='1.0' encoding='us-ascii'?>\n"
8445         "<!DOCTYPE doc SYSTEM 'foo'>\n"
8446         "<doc>&entity;</doc>";
8447     char foo_text[] =
8448         "<!ELEMENT doc (#PCDATA)*>";
8449     unsigned int i;
8450     const unsigned int max_alloc_count = 15;
8451 
8452     for (i = 0; i < max_alloc_count; i++) {
8453         XML_SetParamEntityParsing(parser,
8454                                   XML_PARAM_ENTITY_PARSING_ALWAYS);
8455         XML_SetUserData(parser, foo_text);
8456         XML_SetExternalEntityRefHandler(parser,
8457                                         external_entity_null_loader);
8458         allocation_count = i;
8459         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) != XML_STATUS_ERROR)
8460             break;
8461         /* See comment in test_alloc_parse_xdecl() */
8462         alloc_teardown();
8463         alloc_setup();
8464     }
8465     if (i == 0)
8466         fail("Parsing ignored failing allocator");
8467     else if (i == max_alloc_count)
8468         fail("Parsing failed with allocation count 10");
8469 }
8470 END_TEST
8471 
8472 
8473 static int XMLCALL
external_entity_dbl_handler(XML_Parser parser,const XML_Char * context,const XML_Char * UNUSED_P (base),const XML_Char * UNUSED_P (systemId),const XML_Char * UNUSED_P (publicId))8474 external_entity_dbl_handler(XML_Parser parser,
8475                             const XML_Char *context,
8476                             const XML_Char *UNUSED_P(base),
8477                             const XML_Char *UNUSED_P(systemId),
8478                             const XML_Char *UNUSED_P(publicId))
8479 {
8480     intptr_t callno = (intptr_t)XML_GetUserData(parser);
8481     const char *text;
8482     XML_Parser new_parser;
8483     int i;
8484     const int max_alloc_count = 20;
8485 
8486     if (callno == 0) {
8487         /* First time through, check how many calls to malloc occur */
8488         text = ("<!ELEMENT doc (e+)>\n"
8489                 "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
8490                 "<!ELEMENT e EMPTY>\n");
8491         allocation_count = 10000;
8492         new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8493         if (new_parser == NULL) {
8494             fail("Unable to allocate first external parser");
8495             return XML_STATUS_ERROR;
8496         }
8497         /* Stash the number of calls in the user data */
8498         XML_SetUserData(parser, (void *)(intptr_t)(10000 - allocation_count));
8499     } else {
8500         text = ("<?xml version='1.0' encoding='us-ascii'?>"
8501                 "<e/>");
8502         /* Try at varying levels to exercise more code paths */
8503         for (i = 0; i < max_alloc_count; i++) {
8504             allocation_count = callno + i;
8505             new_parser = XML_ExternalEntityParserCreate(parser,
8506                                                         context,
8507                                                         NULL);
8508             if (new_parser != NULL)
8509                 break;
8510         }
8511         if (i == 0) {
8512             fail("Second external parser unexpectedly created");
8513             XML_ParserFree(new_parser);
8514             return XML_STATUS_ERROR;
8515         }
8516         else if (i == max_alloc_count) {
8517             fail("Second external parser not created");
8518             return XML_STATUS_ERROR;
8519         }
8520     }
8521 
8522     allocation_count = ALLOC_ALWAYS_SUCCEED;
8523     if (_XML_Parse_SINGLE_BYTES(new_parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR) {
8524         xml_failure(new_parser);
8525         return XML_STATUS_ERROR;
8526     }
8527     XML_ParserFree(new_parser);
8528     return XML_STATUS_OK;
8529 }
8530 
8531 /* Test that running out of memory in dtdCopy is correctly reported.
8532  * Based on test_default_ns_from_ext_subset_and_ext_ge()
8533  */
START_TEST(test_alloc_dtd_copy_default_atts)8534 START_TEST(test_alloc_dtd_copy_default_atts)
8535 {
8536     const char *text =
8537         "<?xml version='1.0'?>\n"
8538         "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n"
8539         "  <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n"
8540         "]>\n"
8541         "<doc xmlns='http://example.org/ns1'>\n"
8542         "&en;\n"
8543         "</doc>";
8544 
8545     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8546     XML_SetExternalEntityRefHandler(parser,
8547                                     external_entity_dbl_handler);
8548     XML_SetUserData(parser, NULL);
8549     if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
8550         xml_failure(parser);
8551 }
8552 END_TEST
8553 
8554 
8555 static int XMLCALL
external_entity_dbl_handler_2(XML_Parser parser,const XML_Char * context,const XML_Char * UNUSED_P (base),const XML_Char * UNUSED_P (systemId),const XML_Char * UNUSED_P (publicId))8556 external_entity_dbl_handler_2(XML_Parser parser,
8557                               const XML_Char *context,
8558                               const XML_Char *UNUSED_P(base),
8559                               const XML_Char *UNUSED_P(systemId),
8560                               const XML_Char *UNUSED_P(publicId))
8561 {
8562     intptr_t callno = (intptr_t)XML_GetUserData(parser);
8563     const char *text;
8564     XML_Parser new_parser;
8565     enum XML_Status rv;
8566 
8567     if (callno == 0) {
8568         /* Try different allocation levels for whole exercise */
8569         text = ("<!ELEMENT doc (e+)>\n"
8570                 "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
8571                 "<!ELEMENT e EMPTY>\n");
8572         XML_SetUserData(parser, (void *)(intptr_t)1);
8573         new_parser = XML_ExternalEntityParserCreate(parser,
8574                                                     context,
8575                                                     NULL);
8576         if (new_parser == NULL)
8577             return XML_STATUS_ERROR;
8578         rv = _XML_Parse_SINGLE_BYTES(new_parser, text, strlen(text),
8579                                      XML_TRUE);
8580     } else {
8581         /* Just run through once */
8582         text = ("<?xml version='1.0' encoding='us-ascii'?>"
8583                 "<e/>");
8584         new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8585         if (new_parser == NULL)
8586             return XML_STATUS_ERROR;
8587         rv =_XML_Parse_SINGLE_BYTES(new_parser, text, strlen(text),
8588                                     XML_TRUE);
8589     }
8590     XML_ParserFree(new_parser);
8591     if (rv == XML_STATUS_ERROR)
8592         return XML_STATUS_ERROR;
8593     return XML_STATUS_OK;
8594 }
8595 
8596 /* Test more external entity allocation failure paths */
START_TEST(test_alloc_external_entity)8597 START_TEST(test_alloc_external_entity)
8598 {
8599     const char *text =
8600         "<?xml version='1.0'?>\n"
8601         "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n"
8602         "  <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n"
8603         "]>\n"
8604         "<doc xmlns='http://example.org/ns1'>\n"
8605         "&en;\n"
8606         "</doc>";
8607     int i;
8608     const int alloc_test_max_repeats = 50;
8609 
8610     for (i = 0; i < alloc_test_max_repeats; i++) {
8611         allocation_count = -1;
8612         XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8613         XML_SetExternalEntityRefHandler(parser,
8614                                         external_entity_dbl_handler_2);
8615         XML_SetUserData(parser, NULL);
8616         allocation_count = i;
8617         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
8618                                     XML_TRUE) == XML_STATUS_OK)
8619             break;
8620         /* See comment in test_alloc_parse_xdecl() */
8621         alloc_teardown();
8622         alloc_setup();
8623     }
8624     allocation_count = -1;
8625     if (i == 0)
8626         fail("External entity parsed despite duff allocator");
8627     if (i == alloc_test_max_repeats)
8628         fail("External entity not parsed at max allocation count");
8629 }
8630 END_TEST
8631 
8632 /* Test more allocation failure paths */
8633 static int XMLCALL
external_entity_alloc_set_encoding(XML_Parser parser,const XML_Char * context,const XML_Char * UNUSED_P (base),const XML_Char * UNUSED_P (systemId),const XML_Char * UNUSED_P (publicId))8634 external_entity_alloc_set_encoding(XML_Parser parser,
8635                                    const XML_Char *context,
8636                                    const XML_Char *UNUSED_P(base),
8637                                    const XML_Char *UNUSED_P(systemId),
8638                                    const XML_Char *UNUSED_P(publicId))
8639 {
8640     /* As for external_entity_loader() */
8641     const char *text =
8642         "<?xml encoding='iso-8859-3'?>"
8643         "\xC3\xA9";
8644     XML_Parser ext_parser;
8645     enum XML_Status status;
8646 
8647     ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8648     if (ext_parser == NULL)
8649         return XML_STATUS_ERROR;
8650     if (!XML_SetEncoding(ext_parser, XCS("utf-8"))) {
8651         XML_ParserFree(ext_parser);
8652         return XML_STATUS_ERROR;
8653     }
8654     status = _XML_Parse_SINGLE_BYTES(ext_parser, text, strlen(text),
8655                                      XML_TRUE);
8656     XML_ParserFree(ext_parser);
8657     if (status == XML_STATUS_ERROR)
8658         return XML_STATUS_ERROR;
8659     return XML_STATUS_OK;
8660 }
8661 
START_TEST(test_alloc_ext_entity_set_encoding)8662 START_TEST(test_alloc_ext_entity_set_encoding)
8663 {
8664     const char *text =
8665         "<!DOCTYPE doc [\n"
8666         "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
8667         "]>\n"
8668         "<doc>&en;</doc>";
8669     int i;
8670     const int max_allocation_count = 30;
8671 
8672     for (i = 0; i < max_allocation_count; i++) {
8673         XML_SetExternalEntityRefHandler(parser,
8674                                         external_entity_alloc_set_encoding);
8675         allocation_count = i;
8676         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
8677                                     XML_TRUE) == XML_STATUS_OK)
8678             break;
8679         allocation_count = -1;
8680         /* See comment in test_alloc_parse_xdecl() */
8681         alloc_teardown();
8682         alloc_setup();
8683     }
8684     if (i == 0)
8685         fail("Encoding check succeeded despite failing allocator");
8686     if (i == max_allocation_count)
8687         fail("Encoding failed at max allocation count");
8688 }
8689 END_TEST
8690 
8691 static int XMLCALL
unknown_released_encoding_handler(void * UNUSED_P (data),const XML_Char * encoding,XML_Encoding * info)8692 unknown_released_encoding_handler(void *UNUSED_P(data),
8693                                   const XML_Char *encoding,
8694                                   XML_Encoding *info)
8695 {
8696     if (!xcstrcmp(encoding, XCS("unsupported-encoding"))) {
8697         int i;
8698 
8699         for (i = 0; i < 256; i++)
8700             info->map[i] = i;
8701         info->data = NULL;
8702         info->convert = NULL;
8703         info->release = dummy_release;
8704         return XML_STATUS_OK;
8705     }
8706     return XML_STATUS_ERROR;
8707 }
8708 
8709 /* Test the effects of allocation failure in internal entities.
8710  * Based on test_unknown_encoding_internal_entity
8711  */
START_TEST(test_alloc_internal_entity)8712 START_TEST(test_alloc_internal_entity)
8713 {
8714     const char *text =
8715         "<?xml version='1.0' encoding='unsupported-encoding'?>\n"
8716         "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n"
8717         "<test a='&foo;'/>";
8718     unsigned int i;
8719     const unsigned int max_alloc_count = 20;
8720 
8721     for (i = 0; i < max_alloc_count; i++) {
8722         allocation_count = i;
8723         XML_SetUnknownEncodingHandler(parser,
8724                                       unknown_released_encoding_handler,
8725                                       NULL);
8726         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) != XML_STATUS_ERROR)
8727             break;
8728         /* See comment in test_alloc_parse_xdecl() */
8729         alloc_teardown();
8730         alloc_setup();
8731     }
8732     if (i == 0)
8733         fail("Internal entity worked despite failing allocations");
8734     else if (i == max_alloc_count)
8735         fail("Internal entity failed at max allocation count");
8736 }
8737 END_TEST
8738 
8739 
8740 /* Test the robustness against allocation failure of element handling
8741  * Based on test_dtd_default_handling().
8742  */
START_TEST(test_alloc_dtd_default_handling)8743 START_TEST(test_alloc_dtd_default_handling)
8744 {
8745     const char *text =
8746         "<!DOCTYPE doc [\n"
8747         "<!ENTITY e SYSTEM 'http://example.org/e'>\n"
8748         "<!NOTATION n SYSTEM 'http://example.org/n'>\n"
8749         "<!ENTITY e1 SYSTEM 'http://example.org/e' NDATA n>\n"
8750         "<!ELEMENT doc (#PCDATA)>\n"
8751         "<!ATTLIST doc a CDATA #IMPLIED>\n"
8752         "<?pi in dtd?>\n"
8753         "<!--comment in dtd-->\n"
8754         "]>\n"
8755         "<doc><![CDATA[text in doc]]></doc>";
8756     const XML_Char *expected = XCS("\n\n\n\n\n\n\n\n\n<doc>text in doc</doc>");
8757     CharData storage;
8758     int i;
8759     const int max_alloc_count = 25;
8760 
8761     for (i = 0; i < max_alloc_count; i++) {
8762         allocation_count = i;
8763         dummy_handler_flags = 0;
8764         XML_SetDefaultHandler(parser, accumulate_characters);
8765         XML_SetDoctypeDeclHandler(parser,
8766                                   dummy_start_doctype_handler,
8767                                   dummy_end_doctype_handler);
8768         XML_SetEntityDeclHandler(parser, dummy_entity_decl_handler);
8769         XML_SetNotationDeclHandler(parser, dummy_notation_decl_handler);
8770         XML_SetElementDeclHandler(parser, dummy_element_decl_handler);
8771         XML_SetAttlistDeclHandler(parser, dummy_attlist_decl_handler);
8772         XML_SetProcessingInstructionHandler(parser, dummy_pi_handler);
8773         XML_SetCommentHandler(parser, dummy_comment_handler);
8774         XML_SetCdataSectionHandler(parser,
8775                                    dummy_start_cdata_handler,
8776                                    dummy_end_cdata_handler);
8777         XML_SetUnparsedEntityDeclHandler(
8778             parser,
8779             dummy_unparsed_entity_decl_handler);
8780         CharData_Init(&storage);
8781         XML_SetUserData(parser, &storage);
8782         XML_SetCharacterDataHandler(parser, accumulate_characters);
8783         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
8784                                     XML_TRUE) != XML_STATUS_ERROR)
8785             break;
8786         /* See comment in test_alloc_parse_xdecl() */
8787         alloc_teardown();
8788         alloc_setup();
8789     }
8790     if (i == 0)
8791         fail("Default DTD parsed despite allocation failures");
8792     if (i == max_alloc_count)
8793         fail("Default DTD not parsed with maximum alloc count");
8794     CharData_CheckXMLChars(&storage, expected);
8795     if (dummy_handler_flags != (DUMMY_START_DOCTYPE_HANDLER_FLAG |
8796                                 DUMMY_END_DOCTYPE_HANDLER_FLAG |
8797                                 DUMMY_ENTITY_DECL_HANDLER_FLAG |
8798                                 DUMMY_NOTATION_DECL_HANDLER_FLAG |
8799                                 DUMMY_ELEMENT_DECL_HANDLER_FLAG |
8800                                 DUMMY_ATTLIST_DECL_HANDLER_FLAG |
8801                                 DUMMY_COMMENT_HANDLER_FLAG |
8802                                 DUMMY_PI_HANDLER_FLAG |
8803                                 DUMMY_START_CDATA_HANDLER_FLAG |
8804                                 DUMMY_END_CDATA_HANDLER_FLAG |
8805                                 DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG))
8806         fail("Not all handlers were called");
8807 }
8808 END_TEST
8809 
8810 /* Test robustness of XML_SetEncoding() with a failing allocator */
START_TEST(test_alloc_explicit_encoding)8811 START_TEST(test_alloc_explicit_encoding)
8812 {
8813     int i;
8814     const int max_alloc_count = 5;
8815 
8816     for (i = 0; i < max_alloc_count; i++) {
8817         allocation_count = i;
8818         if (XML_SetEncoding(parser, XCS("us-ascii")) == XML_STATUS_OK)
8819             break;
8820     }
8821     if (i == 0)
8822         fail("Encoding set despite failing allocator");
8823     else if (i == max_alloc_count)
8824         fail("Encoding not set at max allocation count");
8825 }
8826 END_TEST
8827 
8828 /* Test robustness of XML_SetBase against a failing allocator */
START_TEST(test_alloc_set_base)8829 START_TEST(test_alloc_set_base)
8830 {
8831     const XML_Char *new_base = XCS("/local/file/name.xml");
8832     int i;
8833     const int max_alloc_count = 5;
8834 
8835     for (i = 0; i < max_alloc_count; i++) {
8836         allocation_count = i;
8837         if (XML_SetBase(parser, new_base) == XML_STATUS_OK)
8838             break;
8839     }
8840     if (i == 0)
8841         fail("Base set despite failing allocator");
8842     else if (i == max_alloc_count)
8843         fail("Base not set with max allocation count");
8844 }
8845 END_TEST
8846 
8847 /* Test buffer extension in the face of a duff reallocator */
START_TEST(test_alloc_realloc_buffer)8848 START_TEST(test_alloc_realloc_buffer)
8849 {
8850     const char *text = get_buffer_test_text;
8851     void *buffer;
8852     int i;
8853     const int max_realloc_count = 10;
8854 
8855     /* Get a smallish buffer */
8856     for (i = 0; i < max_realloc_count; i++) {
8857         reallocation_count = i;
8858         buffer = XML_GetBuffer(parser, 1536);
8859         if (buffer == NULL)
8860             fail("1.5K buffer reallocation failed");
8861         memcpy(buffer, text, strlen(text));
8862         if (XML_ParseBuffer(parser, strlen(text),
8863                             XML_FALSE) == XML_STATUS_OK)
8864             break;
8865         /* See comment in test_alloc_parse_xdecl() */
8866         alloc_teardown();
8867         alloc_setup();
8868     }
8869     reallocation_count = -1;
8870     if (i == 0)
8871         fail("Parse succeeded with no reallocation");
8872     else if (i == max_realloc_count)
8873         fail("Parse failed with max reallocation count");
8874 }
8875 END_TEST
8876 
8877 /* Same test for external entity parsers */
8878 static int XMLCALL
external_entity_reallocator(XML_Parser parser,const XML_Char * context,const XML_Char * UNUSED_P (base),const XML_Char * UNUSED_P (systemId),const XML_Char * UNUSED_P (publicId))8879 external_entity_reallocator(XML_Parser parser,
8880                             const XML_Char *context,
8881                             const XML_Char *UNUSED_P(base),
8882                             const XML_Char *UNUSED_P(systemId),
8883                             const XML_Char *UNUSED_P(publicId))
8884 {
8885     const char *text = get_buffer_test_text;
8886     XML_Parser ext_parser;
8887     void *buffer;
8888     enum XML_Status status;
8889 
8890     ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8891     if (ext_parser == NULL)
8892         fail("Could not create external entity parser");
8893 
8894     reallocation_count = (intptr_t)XML_GetUserData(parser);
8895     buffer = XML_GetBuffer(ext_parser, 1536);
8896     if (buffer == NULL)
8897         fail("Buffer allocation failed");
8898     memcpy(buffer, text, strlen(text));
8899     status = XML_ParseBuffer(ext_parser, strlen(text), XML_FALSE);
8900     reallocation_count = -1;
8901     XML_ParserFree(ext_parser);
8902     return (status == XML_STATUS_OK) ? XML_STATUS_OK : XML_STATUS_ERROR;
8903 }
8904 
START_TEST(test_alloc_ext_entity_realloc_buffer)8905 START_TEST(test_alloc_ext_entity_realloc_buffer)
8906 {
8907     const char *text =
8908         "<!DOCTYPE doc [\n"
8909         "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
8910         "]>\n"
8911         "<doc>&en;</doc>";
8912     int i;
8913     const int max_realloc_count = 10;
8914 
8915     for (i = 0; i < max_realloc_count; i++) {
8916         XML_SetExternalEntityRefHandler(parser,
8917                                         external_entity_reallocator);
8918         XML_SetUserData(parser, (void *)(intptr_t)i);
8919         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
8920                                     XML_TRUE) == XML_STATUS_OK)
8921             break;
8922         /* See comment in test_alloc_parse_xdecl() */
8923         alloc_teardown();
8924         alloc_setup();
8925     }
8926     if (i == 0)
8927         fail("Succeeded with no reallocations");
8928     if (i == max_realloc_count)
8929         fail("Failed with max reallocations");
8930 }
8931 END_TEST
8932 
8933 /* Test elements with many attributes are handled correctly */
START_TEST(test_alloc_realloc_many_attributes)8934 START_TEST(test_alloc_realloc_many_attributes)
8935 {
8936     const char *text =
8937         "<!DOCTYPE doc [\n"
8938         "<!ATTLIST doc za CDATA 'default'>\n"
8939         "<!ATTLIST doc zb CDATA 'def2'>\n"
8940         "<!ATTLIST doc zc CDATA 'def3'>\n"
8941         "]>\n"
8942         "<doc a='1'"
8943         "     b='2'"
8944         "     c='3'"
8945         "     d='4'"
8946         "     e='5'"
8947         "     f='6'"
8948         "     g='7'"
8949         "     h='8'"
8950         "     i='9'"
8951         "     j='10'"
8952         "     k='11'"
8953         "     l='12'"
8954         "     m='13'"
8955         "     n='14'"
8956         "     p='15'"
8957         "     q='16'"
8958         "     r='17'"
8959         "     s='18'>"
8960         "</doc>";
8961     int i;
8962     const int max_realloc_count = 10;
8963 
8964     for (i = 0; i < max_realloc_count; i++) {
8965         reallocation_count = i;
8966         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
8967                                     XML_TRUE) != XML_STATUS_ERROR)
8968             break;
8969         /* See comment in test_alloc_parse_xdecl() */
8970         alloc_teardown();
8971         alloc_setup();
8972     }
8973     if (i == 0)
8974         fail("Parse succeeded despite no reallocations");
8975     if (i == max_realloc_count)
8976         fail("Parse failed at max reallocations");
8977 }
8978 END_TEST
8979 
8980 /* Test handling of a public entity with failing allocator */
START_TEST(test_alloc_public_entity_value)8981 START_TEST(test_alloc_public_entity_value)
8982 {
8983     const char *text =
8984         "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
8985         "<doc></doc>\n";
8986     char dtd_text[] =
8987         "<!ELEMENT doc EMPTY>\n"
8988         "<!ENTITY % e1 PUBLIC 'foo' 'bar.ent'>\n"
8989         "<!ENTITY % "
8990         /* Each line is 64 characters */
8991         "ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345"
8992         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8993         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8994         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8995         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8996         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8997         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8998         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8999         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9000         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9001         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9002         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9003         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9004         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9005         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9006         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9007         " '%e1;'>\n"
9008         "%e1;\n";
9009     int i;
9010     const int max_alloc_count = 50;
9011 
9012     for (i = 0; i < max_alloc_count; i++) {
9013         allocation_count = i;
9014         dummy_handler_flags = 0;
9015         XML_SetUserData(parser, dtd_text);
9016         XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9017         XML_SetExternalEntityRefHandler(parser, external_entity_public);
9018         /* Provoke a particular code path */
9019         XML_SetEntityDeclHandler(parser, dummy_entity_decl_handler);
9020         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
9021                                     XML_TRUE) != XML_STATUS_ERROR)
9022             break;
9023         /* See comment in test_alloc_parse_xdecl() */
9024         alloc_teardown();
9025         alloc_setup();
9026     }
9027     if (i == 0)
9028         fail("Parsing worked despite failing allocation");
9029     if (i == max_alloc_count)
9030         fail("Parsing failed at max allocation count");
9031     if (dummy_handler_flags != DUMMY_ENTITY_DECL_HANDLER_FLAG)
9032         fail("Entity declaration handler not called");
9033 }
9034 END_TEST
9035 
START_TEST(test_alloc_realloc_subst_public_entity_value)9036 START_TEST(test_alloc_realloc_subst_public_entity_value)
9037 {
9038     const char *text =
9039         "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
9040         "<doc></doc>\n";
9041     char dtd_text[] =
9042         "<!ELEMENT doc EMPTY>\n"
9043         "<!ENTITY % "
9044         /* Each line is 64 characters */
9045         "ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345"
9046         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9047         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9048         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9049         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9050         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9051         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9052         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9053         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9054         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9055         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9056         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9057         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9058         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9059         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9060         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9061         " PUBLIC 'foo' 'bar.ent'>\n"
9062         "%ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345"
9063         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9064         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9065         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9066         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9067         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9068         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9069         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9070         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9071         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9072         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9073         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9074         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9075         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9076         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9077         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP;";
9078     int i;
9079     const int max_realloc_count = 10;
9080 
9081     for (i = 0; i < max_realloc_count; i++) {
9082         reallocation_count = i;
9083         XML_SetUserData(parser, dtd_text);
9084         XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9085         XML_SetExternalEntityRefHandler(parser, external_entity_public);
9086         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
9087                                     XML_TRUE) != XML_STATUS_ERROR)
9088             break;
9089         /* See comment in test_alloc_parse_xdecl() */
9090         alloc_teardown();
9091         alloc_setup();
9092     }
9093     if (i == 0)
9094         fail("Parsing worked despite failing reallocation");
9095     if (i == max_realloc_count)
9096         fail("Parsing failed at max reallocation count");
9097 }
9098 END_TEST
9099 
START_TEST(test_alloc_parse_public_doctype)9100 START_TEST(test_alloc_parse_public_doctype)
9101 {
9102     const char *text =
9103         "<?xml version='1.0' encoding='utf-8'?>\n"
9104         "<!DOCTYPE doc PUBLIC '"
9105         /* 64 characters per line */
9106         "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/"
9107         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9108         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9109         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9110         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9111         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9112         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9113         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9114         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9115         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9116         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9117         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9118         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9119         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9120         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9121         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9122         "' 'test'>\n"
9123         "<doc></doc>";
9124     int i;
9125     const int max_alloc_count = 25;
9126 
9127     for (i = 0; i < max_alloc_count; i++) {
9128         allocation_count = i;
9129         dummy_handler_flags = 0;
9130         XML_SetDoctypeDeclHandler(parser,
9131                                   dummy_start_doctype_decl_handler,
9132                                   dummy_end_doctype_decl_handler);
9133         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
9134                                     XML_TRUE) != XML_STATUS_ERROR)
9135             break;
9136         /* See comment in test_alloc_parse_xdecl() */
9137         alloc_teardown();
9138         alloc_setup();
9139     }
9140     if (i == 0)
9141         fail("Parse succeeded despite failing allocator");
9142     if (i == max_alloc_count)
9143         fail("Parse failed at maximum allocation count");
9144     if (dummy_handler_flags != (DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG |
9145                                 DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG))
9146         fail("Doctype handler functions not called");
9147 }
9148 END_TEST
9149 
START_TEST(test_alloc_parse_public_doctype_long_name)9150 START_TEST(test_alloc_parse_public_doctype_long_name)
9151 {
9152     const char *text =
9153         "<?xml version='1.0' encoding='utf-8'?>\n"
9154         "<!DOCTYPE doc PUBLIC 'http://example.com/foo' '"
9155         /* 64 characters per line */
9156         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
9157         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
9158         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
9159         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
9160         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
9161         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
9162         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
9163         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
9164         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
9165         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
9166         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
9167         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
9168         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
9169         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
9170         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
9171         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
9172         "'>\n"
9173         "<doc></doc>";
9174     int i;
9175     const int max_alloc_count = 25;
9176 
9177     for (i = 0; i < max_alloc_count; i++) {
9178         allocation_count = i;
9179         XML_SetDoctypeDeclHandler(parser,
9180                                   dummy_start_doctype_decl_handler,
9181                                   dummy_end_doctype_decl_handler);
9182         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
9183                                     XML_TRUE) != XML_STATUS_ERROR)
9184             break;
9185         /* See comment in test_alloc_parse_xdecl() */
9186         alloc_teardown();
9187         alloc_setup();
9188     }
9189     if (i == 0)
9190         fail("Parse succeeded despite failing allocator");
9191     if (i == max_alloc_count)
9192         fail("Parse failed at maximum allocation count");
9193 }
9194 END_TEST
9195 
9196 static int XMLCALL
external_entity_alloc(XML_Parser parser,const XML_Char * context,const XML_Char * UNUSED_P (base),const XML_Char * UNUSED_P (systemId),const XML_Char * UNUSED_P (publicId))9197 external_entity_alloc(XML_Parser parser,
9198                       const XML_Char *context,
9199                       const XML_Char *UNUSED_P(base),
9200                       const XML_Char *UNUSED_P(systemId),
9201                       const XML_Char *UNUSED_P(publicId))
9202 {
9203     const char *text = (const char *)XML_GetUserData(parser);
9204     XML_Parser ext_parser;
9205     int parse_res;
9206 
9207     ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
9208     if (ext_parser == NULL)
9209         return XML_STATUS_ERROR;
9210     parse_res = _XML_Parse_SINGLE_BYTES(ext_parser, text, strlen(text),
9211                                         XML_TRUE);
9212     XML_ParserFree(ext_parser);
9213     return parse_res;
9214 }
9215 
9216 /* Test foreign DTD handling */
START_TEST(test_alloc_set_foreign_dtd)9217 START_TEST(test_alloc_set_foreign_dtd)
9218 {
9219     const char *text1 =
9220         "<?xml version='1.0' encoding='us-ascii'?>\n"
9221         "<doc>&entity;</doc>";
9222     char text2[] = "<!ELEMENT doc (#PCDATA)*>";
9223     int i;
9224     const int max_alloc_count = 25;
9225 
9226     for (i = 0; i < max_alloc_count; i++) {
9227         allocation_count = i;
9228         XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9229         XML_SetUserData(parser, &text2);
9230         XML_SetExternalEntityRefHandler(parser, external_entity_alloc);
9231         if (XML_UseForeignDTD(parser, XML_TRUE) != XML_ERROR_NONE)
9232             fail("Could not set foreign DTD");
9233         if (_XML_Parse_SINGLE_BYTES(parser, text1, strlen(text1),
9234                                     XML_TRUE) != XML_STATUS_ERROR)
9235             break;
9236         /* See comment in test_alloc_parse_xdecl() */
9237         alloc_teardown();
9238         alloc_setup();
9239     }
9240     if (i == 0)
9241         fail("Parse succeeded despite failing allocator");
9242     if (i == max_alloc_count)
9243         fail("Parse failed at maximum allocation count");
9244 }
9245 END_TEST
9246 
9247 /* Test based on ibm/valid/P32/ibm32v04.xml */
START_TEST(test_alloc_attribute_enum_value)9248 START_TEST(test_alloc_attribute_enum_value)
9249 {
9250     const char *text =
9251         "<?xml version='1.0' standalone='no'?>\n"
9252         "<!DOCTYPE animal SYSTEM 'test.dtd'>\n"
9253         "<animal>This is a \n    <a/>  \n\nyellow tiger</animal>";
9254     char dtd_text[] =
9255         "<!ELEMENT animal (#PCDATA|a)*>\n"
9256         "<!ELEMENT a EMPTY>\n"
9257         "<!ATTLIST animal xml:space (default|preserve) 'preserve'>";
9258     int i;
9259     const int max_alloc_count = 30;
9260 
9261     for (i = 0; i < max_alloc_count; i++) {
9262         allocation_count = i;
9263         XML_SetExternalEntityRefHandler(parser, external_entity_alloc);
9264         XML_SetUserData(parser, dtd_text);
9265         XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9266         /* An attribute list handler provokes a different code path */
9267         XML_SetAttlistDeclHandler(parser, dummy_attlist_decl_handler);
9268         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
9269                                     XML_TRUE) != XML_STATUS_ERROR)
9270             break;
9271         /* See comment in test_alloc_parse_xdecl() */
9272         alloc_teardown();
9273         alloc_setup();
9274     }
9275     if (i == 0)
9276         fail("Parse succeeded despite failing allocator");
9277     if (i == max_alloc_count)
9278         fail("Parse failed at maximum allocation count");
9279 }
9280 END_TEST
9281 
9282 /* Test attribute enums sufficient to overflow the string pool */
START_TEST(test_alloc_realloc_attribute_enum_value)9283 START_TEST(test_alloc_realloc_attribute_enum_value)
9284 {
9285     const char *text =
9286         "<?xml version='1.0' standalone='no'?>\n"
9287         "<!DOCTYPE animal SYSTEM 'test.dtd'>\n"
9288         "<animal>This is a yellow tiger</animal>";
9289     /* We wish to define a collection of attribute enums that will
9290      * cause the string pool storing them to have to expand.  This
9291      * means more than 1024 bytes, including the parentheses and
9292      * separator bars.
9293      */
9294     char dtd_text[] =
9295         "<!ELEMENT animal (#PCDATA)*>\n"
9296         "<!ATTLIST animal thing "
9297         "(default"
9298         /* Each line is 64 characters */
9299         "|ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9300         "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9301         "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9302         "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9303         "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9304         "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9305         "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9306         "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9307         "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9308         "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9309         "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9310         "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9311         "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9312         "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9313         "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9314         "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO)"
9315         " 'default'>";
9316     int i;
9317     const int max_realloc_count = 10;
9318 
9319     for (i = 0; i < max_realloc_count; i++) {
9320         reallocation_count = i;
9321         XML_SetExternalEntityRefHandler(parser, external_entity_alloc);
9322         XML_SetUserData(parser, dtd_text);
9323         XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9324         /* An attribute list handler provokes a different code path */
9325         XML_SetAttlistDeclHandler(parser, dummy_attlist_decl_handler);
9326         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
9327                                     XML_TRUE) != XML_STATUS_ERROR)
9328             break;
9329         /* See comment in test_alloc_parse_xdecl() */
9330         alloc_teardown();
9331         alloc_setup();
9332     }
9333     if (i == 0)
9334         fail("Parse succeeded despite failing reallocator");
9335     if (i == max_realloc_count)
9336         fail("Parse failed at maximum reallocation count");
9337 }
9338 END_TEST
9339 
9340 /* Test attribute enums in a #IMPLIED attribute forcing pool growth */
START_TEST(test_alloc_realloc_implied_attribute)9341 START_TEST(test_alloc_realloc_implied_attribute)
9342 {
9343     /* Forcing this particular code path is a balancing act.  The
9344      * addition of the closing parenthesis and terminal NUL must be
9345      * what pushes the string of enums over the 1024-byte limit,
9346      * otherwise a different code path will pick up the realloc.
9347      */
9348     const char *text =
9349         "<!DOCTYPE doc [\n"
9350         "<!ELEMENT doc EMPTY>\n"
9351         "<!ATTLIST doc a "
9352         /* Each line is 64 characters */
9353         "(ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9354         "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9355         "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9356         "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9357         "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9358         "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9359         "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9360         "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9361         "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9362         "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9363         "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9364         "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9365         "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9366         "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9367         "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9368         "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN)"
9369         " #IMPLIED>\n"
9370         "]><doc/>";
9371     int i;
9372     const int max_realloc_count = 10;
9373 
9374     for (i = 0; i < max_realloc_count; i++) {
9375         reallocation_count = i;
9376         XML_SetAttlistDeclHandler(parser, dummy_attlist_decl_handler);
9377         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
9378                                     XML_TRUE) != XML_STATUS_ERROR)
9379             break;
9380         /* See comment in test_alloc_parse_xdecl() */
9381         alloc_teardown();
9382         alloc_setup();
9383     }
9384     if (i == 0)
9385         fail("Parse succeeded despite failing reallocator");
9386     if (i == max_realloc_count)
9387         fail("Parse failed at maximum reallocation count");
9388 }
9389 END_TEST
9390 
9391 /* Test attribute enums in a defaulted attribute forcing pool growth */
START_TEST(test_alloc_realloc_default_attribute)9392 START_TEST(test_alloc_realloc_default_attribute)
9393 {
9394     /* Forcing this particular code path is a balancing act.  The
9395      * addition of the closing parenthesis and terminal NUL must be
9396      * what pushes the string of enums over the 1024-byte limit,
9397      * otherwise a different code path will pick up the realloc.
9398      */
9399     const char *text =
9400         "<!DOCTYPE doc [\n"
9401         "<!ELEMENT doc EMPTY>\n"
9402         "<!ATTLIST doc a "
9403         /* Each line is 64 characters */
9404         "(ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9405         "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9406         "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9407         "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9408         "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9409         "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9410         "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9411         "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9412         "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9413         "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9414         "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9415         "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9416         "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9417         "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9418         "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9419         "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN)"
9420         " 'ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO'"
9421         ">\n]><doc/>";
9422     int i;
9423     const int max_realloc_count = 10;
9424 
9425     for (i = 0; i < max_realloc_count; i++) {
9426         reallocation_count = i;
9427         XML_SetAttlistDeclHandler(parser, dummy_attlist_decl_handler);
9428         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
9429                                     XML_TRUE) != XML_STATUS_ERROR)
9430             break;
9431         /* See comment in test_alloc_parse_xdecl() */
9432         alloc_teardown();
9433         alloc_setup();
9434     }
9435     if (i == 0)
9436         fail("Parse succeeded despite failing reallocator");
9437     if (i == max_realloc_count)
9438         fail("Parse failed at maximum reallocation count");
9439 }
9440 END_TEST
9441 
9442 /* Test long notation name with dodgy allocator */
START_TEST(test_alloc_notation)9443 START_TEST(test_alloc_notation)
9444 {
9445     const char *text =
9446         "<!DOCTYPE doc [\n"
9447         "<!NOTATION "
9448         /* Each line is 64 characters */
9449         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
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         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9463         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9464         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9465         " SYSTEM 'http://example.org/n'>\n"
9466         "<!ENTITY e SYSTEM 'http://example.org/e' NDATA "
9467         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9468         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9469         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9470         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9471         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9472         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9473         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9474         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9475         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9476         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9477         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9478         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9479         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9480         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9481         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9482         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9483         ">\n"
9484         "<!ELEMENT doc EMPTY>\n"
9485         "]>\n<doc/>";
9486     int i;
9487     const int max_alloc_count = 20;
9488 
9489     for (i = 0; i < max_alloc_count; i++) {
9490         allocation_count = i;
9491         dummy_handler_flags = 0;
9492         XML_SetNotationDeclHandler(parser, dummy_notation_decl_handler);
9493         XML_SetEntityDeclHandler(parser, dummy_entity_decl_handler);
9494         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
9495                                     XML_TRUE) != XML_STATUS_ERROR)
9496             break;
9497         /* See comment in test_alloc_parse_xdecl() */
9498         alloc_teardown();
9499         alloc_setup();
9500     }
9501     if (i == 0)
9502         fail("Parse succeeded despite allocation failures");
9503     if (i == max_alloc_count)
9504         fail("Parse failed at maximum allocation count");
9505     if (dummy_handler_flags != (DUMMY_ENTITY_DECL_HANDLER_FLAG |
9506                                 DUMMY_NOTATION_DECL_HANDLER_FLAG))
9507         fail("Entity declaration handler not called");
9508 }
9509 END_TEST
9510 
9511 /* Test public notation with dodgy allocator */
START_TEST(test_alloc_public_notation)9512 START_TEST(test_alloc_public_notation)
9513 {
9514     const char *text =
9515         "<!DOCTYPE doc [\n"
9516         "<!NOTATION note PUBLIC '"
9517         /* 64 characters per line */
9518         "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/"
9519         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9520         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9521         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9522         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9523         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9524         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9525         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9526         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9527         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9528         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9529         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9530         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9531         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9532         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9533         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9534         "' 'foo'>\n"
9535         "<!ENTITY e SYSTEM 'http://example.com/e' NDATA note>\n"
9536         "<!ELEMENT doc EMPTY>\n"
9537         "]>\n<doc/>";
9538     int i;
9539     const int max_alloc_count = 20;
9540 
9541     for (i = 0; i < max_alloc_count; i++) {
9542         allocation_count = i;
9543         dummy_handler_flags = 0;
9544         XML_SetNotationDeclHandler(parser, dummy_notation_decl_handler);
9545         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
9546                                     XML_TRUE) != XML_STATUS_ERROR)
9547             break;
9548         /* See comment in test_alloc_parse_xdecl() */
9549         alloc_teardown();
9550         alloc_setup();
9551     }
9552     if (i == 0)
9553         fail("Parse succeeded despite allocation failures");
9554     if (i == max_alloc_count)
9555         fail("Parse failed at maximum allocation count");
9556     if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG)
9557         fail("Notation handler not called");
9558 }
9559 END_TEST
9560 
9561 /* Test public notation with dodgy allocator */
START_TEST(test_alloc_system_notation)9562 START_TEST(test_alloc_system_notation)
9563 {
9564     const char *text =
9565         "<!DOCTYPE doc [\n"
9566         "<!NOTATION note SYSTEM '"
9567         /* 64 characters per line */
9568         "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/"
9569         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9570         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9571         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9572         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9573         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9574         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9575         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9576         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9577         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9578         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9579         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9580         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9581         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9582         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9583         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9584         "'>\n"
9585         "<!ENTITY e SYSTEM 'http://example.com/e' NDATA note>\n"
9586         "<!ELEMENT doc EMPTY>\n"
9587         "]>\n<doc/>";
9588     int i;
9589     const int max_alloc_count = 20;
9590 
9591     for (i = 0; i < max_alloc_count; i++) {
9592         allocation_count = i;
9593         dummy_handler_flags = 0;
9594         XML_SetNotationDeclHandler(parser, dummy_notation_decl_handler);
9595         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
9596                                     XML_TRUE) != XML_STATUS_ERROR)
9597             break;
9598         /* See comment in test_alloc_parse_xdecl() */
9599         alloc_teardown();
9600         alloc_setup();
9601     }
9602     if (i == 0)
9603         fail("Parse succeeded despite allocation failures");
9604     if (i == max_alloc_count)
9605         fail("Parse failed at maximum allocation count");
9606     if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG)
9607         fail("Notation handler not called");
9608 }
9609 END_TEST
9610 
START_TEST(test_alloc_nested_groups)9611 START_TEST(test_alloc_nested_groups)
9612 {
9613     const char *text =
9614         "<!DOCTYPE doc [\n"
9615         "<!ELEMENT doc "
9616         /* Sixteen elements per line */
9617         "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,"
9618         "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?"
9619         "))))))))))))))))))))))))))))))))>\n"
9620         "<!ELEMENT e EMPTY>"
9621         "]>\n"
9622         "<doc><e/></doc>";
9623     CharData storage;
9624     int i;
9625     const int max_alloc_count = 20;
9626 
9627     for (i = 0; i < max_alloc_count; i++) {
9628         allocation_count = i;
9629         CharData_Init(&storage);
9630         XML_SetElementDeclHandler(parser, dummy_element_decl_handler);
9631         XML_SetStartElementHandler(parser, record_element_start_handler);
9632         XML_SetUserData(parser, &storage);
9633         dummy_handler_flags = 0;
9634         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
9635                                     XML_TRUE) != XML_STATUS_ERROR)
9636             break;
9637         /* See comment in test_alloc_parse_xdecl() */
9638         alloc_teardown();
9639         alloc_setup();
9640     }
9641 
9642     if (i == 0)
9643         fail("Parse succeeded despite failing reallocator");
9644     if (i == max_alloc_count)
9645         fail("Parse failed at maximum reallocation count");
9646     CharData_CheckXMLChars(&storage, XCS("doce"));
9647     if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9648         fail("Element handler not fired");
9649 }
9650 END_TEST
9651 
START_TEST(test_alloc_realloc_nested_groups)9652 START_TEST(test_alloc_realloc_nested_groups)
9653 {
9654     const char *text =
9655         "<!DOCTYPE doc [\n"
9656         "<!ELEMENT doc "
9657         /* Sixteen elements per line */
9658         "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,"
9659         "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?"
9660         "))))))))))))))))))))))))))))))))>\n"
9661         "<!ELEMENT e EMPTY>"
9662         "]>\n"
9663         "<doc><e/></doc>";
9664     CharData storage;
9665     int i;
9666     const int max_realloc_count = 10;
9667 
9668     for (i = 0; i < max_realloc_count; i++) {
9669         reallocation_count = i;
9670         CharData_Init(&storage);
9671         XML_SetElementDeclHandler(parser, dummy_element_decl_handler);
9672         XML_SetStartElementHandler(parser, record_element_start_handler);
9673         XML_SetUserData(parser, &storage);
9674         dummy_handler_flags = 0;
9675         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
9676                                     XML_TRUE) != XML_STATUS_ERROR)
9677             break;
9678         /* See comment in test_alloc_parse_xdecl() */
9679         alloc_teardown();
9680         alloc_setup();
9681     }
9682 
9683     if (i == 0)
9684         fail("Parse succeeded despite failing reallocator");
9685     if (i == max_realloc_count)
9686         fail("Parse failed at maximum reallocation count");
9687     CharData_CheckXMLChars(&storage, XCS("doce"));
9688     if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9689         fail("Element handler not fired");
9690 }
9691 END_TEST
9692 
START_TEST(test_alloc_large_group)9693 START_TEST(test_alloc_large_group)
9694 {
9695     const char *text =
9696         "<!DOCTYPE doc [\n"
9697         "<!ELEMENT doc ("
9698         "a1|a2|a3|a4|a5|a6|a7|a8|"
9699         "b1|b2|b3|b4|b5|b6|b7|b8|"
9700         "c1|c2|c3|c4|c5|c6|c7|c8|"
9701         "d1|d2|d3|d4|d5|d6|d7|d8|"
9702         "e1"
9703         ")+>\n"
9704         "]>\n"
9705         "<doc>\n"
9706         "<a1/>\n"
9707         "</doc>\n";
9708     int i;
9709     const int max_alloc_count = 50;
9710 
9711     for (i = 0; i < max_alloc_count; i++) {
9712         allocation_count = i;
9713         XML_SetElementDeclHandler(parser, dummy_element_decl_handler);
9714         dummy_handler_flags = 0;
9715         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
9716                                     XML_TRUE) != XML_STATUS_ERROR)
9717             break;
9718         /* See comment in test_alloc_parse_xdecl() */
9719         alloc_teardown();
9720         alloc_setup();
9721     }
9722     if (i == 0)
9723         fail("Parse succeeded despite failing allocator");
9724     if (i == max_alloc_count)
9725         fail("Parse failed at maximum allocation count");
9726     if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9727         fail("Element handler flag not raised");
9728 }
9729 END_TEST
9730 
START_TEST(test_alloc_realloc_group_choice)9731 START_TEST(test_alloc_realloc_group_choice)
9732 {
9733     const char *text =
9734         "<!DOCTYPE doc [\n"
9735         "<!ELEMENT doc ("
9736         "a1|a2|a3|a4|a5|a6|a7|a8|"
9737         "b1|b2|b3|b4|b5|b6|b7|b8|"
9738         "c1|c2|c3|c4|c5|c6|c7|c8|"
9739         "d1|d2|d3|d4|d5|d6|d7|d8|"
9740         "e1"
9741         ")+>\n"
9742         "]>\n"
9743         "<doc>\n"
9744         "<a1/>\n"
9745         "<b2 attr='foo'>This is a foo</b2>\n"
9746         "<c3></c3>\n"
9747         "</doc>\n";
9748     int i;
9749     const int max_realloc_count = 10;
9750 
9751     for (i = 0; i < max_realloc_count; i++) {
9752         reallocation_count = i;
9753         XML_SetElementDeclHandler(parser, dummy_element_decl_handler);
9754         dummy_handler_flags = 0;
9755         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
9756                                     XML_TRUE) != XML_STATUS_ERROR)
9757             break;
9758         /* See comment in test_alloc_parse_xdecl() */
9759         alloc_teardown();
9760         alloc_setup();
9761     }
9762     if (i == 0)
9763         fail("Parse succeeded despite failing reallocator");
9764     if (i == max_realloc_count)
9765         fail("Parse failed at maximum reallocation count");
9766     if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9767         fail("Element handler flag not raised");
9768 }
9769 END_TEST
9770 
START_TEST(test_alloc_pi_in_epilog)9771 START_TEST(test_alloc_pi_in_epilog)
9772 {
9773     const char *text =
9774         "<doc></doc>\n"
9775         "<?pi in epilog?>";
9776     int i;
9777     const int max_alloc_count = 15;
9778 
9779     for (i = 0; i < max_alloc_count; i++) {
9780         allocation_count = i;
9781         XML_SetProcessingInstructionHandler(parser, dummy_pi_handler);
9782         dummy_handler_flags = 0;
9783         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
9784                                     XML_TRUE) != XML_STATUS_ERROR)
9785             break;
9786         /* See comment in test_alloc_parse_xdecl() */
9787         alloc_teardown();
9788         alloc_setup();
9789     }
9790     if (i == 0)
9791         fail("Parse completed despite failing allocator");
9792     if (i == max_alloc_count)
9793         fail("Parse failed at maximum allocation count");
9794     if (dummy_handler_flags != DUMMY_PI_HANDLER_FLAG)
9795         fail("Processing instruction handler not invoked");
9796 }
9797 END_TEST
9798 
START_TEST(test_alloc_comment_in_epilog)9799 START_TEST(test_alloc_comment_in_epilog)
9800 {
9801     const char *text =
9802         "<doc></doc>\n"
9803         "<!-- comment in epilog -->";
9804     int i;
9805     const int max_alloc_count = 15;
9806 
9807     for (i = 0; i < max_alloc_count; i++) {
9808         allocation_count = i;
9809         XML_SetCommentHandler(parser, dummy_comment_handler);
9810         dummy_handler_flags = 0;
9811         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
9812                                     XML_TRUE) != XML_STATUS_ERROR)
9813             break;
9814         /* See comment in test_alloc_parse_xdecl() */
9815         alloc_teardown();
9816         alloc_setup();
9817     }
9818     if (i == 0)
9819         fail("Parse completed despite failing allocator");
9820     if (i == max_alloc_count)
9821         fail("Parse failed at maximum allocation count");
9822     if (dummy_handler_flags != DUMMY_COMMENT_HANDLER_FLAG)
9823         fail("Processing instruction handler not invoked");
9824 }
9825 END_TEST
9826 
START_TEST(test_alloc_realloc_long_attribute_value)9827 START_TEST(test_alloc_realloc_long_attribute_value)
9828 {
9829     const char *text =
9830         "<!DOCTYPE doc [<!ENTITY foo '"
9831         /* Each line is 64 characters */
9832         "This entity will be substituted as an attribute value, and is   "
9833         "calculated to be exactly long enough that the terminating NUL   "
9834         "that the library adds internally will trigger the string pool to"
9835         "grow. GHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9836         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9837         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9838         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9839         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9840         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9841         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9842         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9843         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9844         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9845         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9846         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9847         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9848         "'>]>\n"
9849         "<doc a='&foo;'></doc>";
9850     int i;
9851     const int max_realloc_count = 10;
9852 
9853     for (i = 0; i < max_realloc_count; i++) {
9854         reallocation_count = i;
9855         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
9856                                     XML_TRUE) != XML_STATUS_ERROR)
9857             break;
9858         /* See comment in test_alloc_parse_xdecl() */
9859         alloc_teardown();
9860         alloc_setup();
9861     }
9862     if (i == 0)
9863         fail("Parse succeeded despite failing reallocator");
9864     if (i == max_realloc_count)
9865         fail("Parse failed at maximum reallocation count");
9866 }
9867 END_TEST
9868 
START_TEST(test_alloc_attribute_whitespace)9869 START_TEST(test_alloc_attribute_whitespace)
9870 {
9871     const char *text = "<doc a=' '></doc>";
9872     int i;
9873     const int max_alloc_count = 15;
9874 
9875     for (i = 0; i < max_alloc_count; i++) {
9876         allocation_count = i;
9877         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
9878                                     XML_TRUE) != XML_STATUS_ERROR)
9879             break;
9880         /* See comment in test_alloc_parse_xdecl() */
9881         alloc_teardown();
9882         alloc_setup();
9883     }
9884     if (i == 0)
9885         fail("Parse succeeded despite failing allocator");
9886     if (i == max_alloc_count)
9887         fail("Parse failed at maximum allocation count");
9888 }
9889 END_TEST
9890 
START_TEST(test_alloc_attribute_predefined_entity)9891 START_TEST(test_alloc_attribute_predefined_entity)
9892 {
9893     const char *text = "<doc a='&amp;'></doc>";
9894     int i;
9895     const int max_alloc_count = 15;
9896 
9897     for (i = 0; i < max_alloc_count; i++) {
9898         allocation_count = i;
9899         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
9900                                     XML_TRUE) != XML_STATUS_ERROR)
9901             break;
9902         /* See comment in test_alloc_parse_xdecl() */
9903         alloc_teardown();
9904         alloc_setup();
9905     }
9906     if (i == 0)
9907         fail("Parse succeeded despite failing allocator");
9908     if (i == max_alloc_count)
9909         fail("Parse failed at maximum allocation count");
9910 }
9911 END_TEST
9912 
9913 /* Test that a character reference at the end of a suitably long
9914  * default value for an attribute can trigger pool growth, and recovers
9915  * if the allocator fails on it.
9916  */
START_TEST(test_alloc_long_attr_default_with_char_ref)9917 START_TEST(test_alloc_long_attr_default_with_char_ref)
9918 {
9919     const char *text =
9920         "<!DOCTYPE doc [<!ATTLIST doc a CDATA '"
9921         /* 64 characters per line */
9922         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9923         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9924         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9925         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9926         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9927         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9928         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9929         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9930         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9931         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9932         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9933         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9934         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9935         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9936         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9937         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHI"
9938         "&#x31;'>]>\n"
9939         "<doc/>";
9940     int i;
9941     const int max_alloc_count = 20;
9942 
9943     for (i = 0; i < max_alloc_count; i++) {
9944         allocation_count = i;
9945         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
9946                                     XML_TRUE) != XML_STATUS_ERROR)
9947             break;
9948         /* See comment in test_alloc_parse_xdecl() */
9949         alloc_teardown();
9950         alloc_setup();
9951     }
9952     if (i == 0)
9953         fail("Parse succeeded despite failing allocator");
9954     if (i == max_alloc_count)
9955         fail("Parse failed at maximum allocation count");
9956 }
9957 END_TEST
9958 
9959 /* Test that a long character reference substitution triggers a pool
9960  * expansion correctly for an attribute value.
9961  */
START_TEST(test_alloc_long_attr_value)9962 START_TEST(test_alloc_long_attr_value)
9963 {
9964     const char *text =
9965         "<!DOCTYPE test [<!ENTITY foo '\n"
9966         /* 64 characters per line */
9967         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9968         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9969         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9970         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9971         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9972         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9973         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9974         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9975         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9976         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9977         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9978         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9979         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9980         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9981         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9982         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9983         "'>]>\n"
9984         "<test a='&foo;'/>";
9985     int i;
9986     const int max_alloc_count = 25;
9987 
9988     for (i = 0; i < max_alloc_count; i++) {
9989         allocation_count = i;
9990         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
9991                                     XML_TRUE) != XML_STATUS_ERROR)
9992             break;
9993         /* See comment in test_alloc_parse_xdecl() */
9994         alloc_teardown();
9995         alloc_setup();
9996     }
9997     if (i == 0)
9998         fail("Parse succeeded despite failing allocator");
9999     if (i == max_alloc_count)
10000         fail("Parse failed at maximum allocation count");
10001 }
10002 END_TEST
10003 
10004 /* Test that an error in a nested parameter entity substitution is
10005  * handled correctly.  It seems unlikely that the code path being
10006  * exercised can be reached purely by carefully crafted XML, but an
10007  * allocation error in the right place will definitely do it.
10008  */
START_TEST(test_alloc_nested_entities)10009 START_TEST(test_alloc_nested_entities)
10010 {
10011     const char *text =
10012         "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n"
10013         "<doc />";
10014     ExtFaults test_data = {
10015         "<!ENTITY % pe1 '"
10016         /* 64 characters per line */
10017         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10018         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10019         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10020         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10021         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10022         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10023         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10024         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10025         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10026         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10027         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10028         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10029         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10030         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10031         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10032         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10033         "'>\n"
10034         "<!ENTITY % pe2 '%pe1;'>\n"
10035         "%pe2;",
10036         "Memory Fail not faulted",
10037         NULL,
10038         XML_ERROR_NO_MEMORY
10039     };
10040 
10041     /* Causes an allocation error in a nested storeEntityValue() */
10042     allocation_count = 12;
10043     XML_SetUserData(parser, &test_data);
10044     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
10045     XML_SetExternalEntityRefHandler(parser, external_entity_faulter);
10046     expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
10047                    "Entity allocation failure not noted");
10048 }
10049 END_TEST
10050 
START_TEST(test_alloc_realloc_param_entity_newline)10051 START_TEST(test_alloc_realloc_param_entity_newline)
10052 {
10053     const char *text =
10054         "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
10055         "<doc/>";
10056     char dtd_text[] =
10057         "<!ENTITY % pe '<!ATTLIST doc att CDATA \""
10058         /* 64 characters per line */
10059         "This default value is carefully crafted so that the carriage    "
10060         "return right at the end of the entity string causes an internal "
10061         "string pool to have to grow.  This allows us to test the alloc  "
10062         "failure path from that point. OPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10063         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10064         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10065         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10066         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10067         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10068         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10069         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10070         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10071         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10072         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10073         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10074         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDE"
10075         "\">\n'>"
10076         "%pe;\n";
10077     int i;
10078     const int max_realloc_count = 5;
10079 
10080     for (i = 0; i < max_realloc_count; i++) {
10081         reallocation_count = i;
10082         XML_SetUserData(parser, dtd_text);
10083         XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
10084         XML_SetExternalEntityRefHandler(parser, external_entity_alloc);
10085         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
10086                                     XML_TRUE) != XML_STATUS_ERROR)
10087             break;
10088         /* See comment in test_alloc_parse_xdecl() */
10089         alloc_teardown();
10090         alloc_setup();
10091     }
10092     if (i == 0)
10093         fail("Parse succeeded despite failing reallocator");
10094     if (i == max_realloc_count)
10095         fail("Parse failed at maximum reallocation count");
10096 }
10097 END_TEST
10098 
START_TEST(test_alloc_realloc_ce_extends_pe)10099 START_TEST(test_alloc_realloc_ce_extends_pe)
10100 {
10101     const char *text =
10102         "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
10103         "<doc/>";
10104     char dtd_text[] =
10105         "<!ENTITY % pe '<!ATTLIST doc att CDATA \""
10106         /* 64 characters per line */
10107         "This default value is carefully crafted so that the character   "
10108         "entity at the end causes an internal string pool to have to     "
10109         "grow.  This allows us to test the allocation failure path from  "
10110         "that point onwards. EFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10111         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10112         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10113         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10114         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10115         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10116         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10117         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10118         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10119         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10120         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10121         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10122         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFG&#x51;"
10123         "\">\n'>"
10124         "%pe;\n";
10125     int i;
10126     const int max_realloc_count = 5;
10127 
10128     for (i = 0; i < max_realloc_count; i++) {
10129         reallocation_count = i;
10130         XML_SetUserData(parser, dtd_text);
10131         XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
10132         XML_SetExternalEntityRefHandler(parser, external_entity_alloc);
10133         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
10134                                     XML_TRUE) != XML_STATUS_ERROR)
10135             break;
10136         /* See comment in test_alloc_parse_xdecl() */
10137         alloc_teardown();
10138         alloc_setup();
10139     }
10140     if (i == 0)
10141         fail("Parse succeeded despite failing reallocator");
10142     if (i == max_realloc_count)
10143         fail("Parse failed at maximum reallocation count");
10144 }
10145 END_TEST
10146 
START_TEST(test_alloc_realloc_attributes)10147 START_TEST(test_alloc_realloc_attributes)
10148 {
10149     const char *text =
10150         "<!DOCTYPE doc [\n"
10151         "  <!ATTLIST doc\n"
10152         "    a1  (a|b|c)   'a'\n"
10153         "    a2  (foo|bar) #IMPLIED\n"
10154         "    a3  NMTOKEN   #IMPLIED\n"
10155         "    a4  NMTOKENS  #IMPLIED\n"
10156         "    a5  ID        #IMPLIED\n"
10157         "    a6  IDREF     #IMPLIED\n"
10158         "    a7  IDREFS    #IMPLIED\n"
10159         "    a8  ENTITY    #IMPLIED\n"
10160         "    a9  ENTITIES  #IMPLIED\n"
10161         "    a10 CDATA     #IMPLIED\n"
10162         "  >]>\n"
10163         "<doc>wombat</doc>\n";
10164     int i;
10165     const int max_realloc_count = 5;
10166 
10167     for (i = 0; i < max_realloc_count; i++) {
10168         reallocation_count = i;
10169         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
10170                                     XML_TRUE) != XML_STATUS_ERROR)
10171             break;
10172         /* See comment in test_alloc_parse_xdecl() */
10173         alloc_teardown();
10174         alloc_setup();
10175     }
10176 
10177     if (i == 0)
10178         fail("Parse succeeded despite failing reallocator");
10179     if (i == max_realloc_count)
10180         fail("Parse failed at maximum reallocation count");
10181 }
10182 END_TEST
10183 
START_TEST(test_alloc_long_doc_name)10184 START_TEST(test_alloc_long_doc_name)
10185 {
10186     const char *text =
10187         /* 64 characters per line */
10188         "<LongRootElementNameThatWillCauseTheNextAllocationToExpandTheStr"
10189         "ingPoolForTheDTDQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10190         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10191         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10192         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10193         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10194         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10195         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10196         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10197         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10198         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10199         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10200         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10201         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10202         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10203         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10204         " a='1'/>";
10205     int i;
10206     const int max_alloc_count = 20;
10207 
10208     for (i = 0; i < max_alloc_count; i++) {
10209         allocation_count = i;
10210         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
10211                                     XML_TRUE) != XML_STATUS_ERROR)
10212             break;
10213         /* See comment in test_alloc_parse_xdecl() */
10214         alloc_teardown();
10215         alloc_setup();
10216     }
10217     if (i == 0)
10218         fail("Parsing worked despite failing reallocations");
10219     else if (i == max_alloc_count)
10220         fail("Parsing failed even at max reallocation count");
10221 }
10222 END_TEST
10223 
START_TEST(test_alloc_long_base)10224 START_TEST(test_alloc_long_base)
10225 {
10226     const char *text =
10227         "<!DOCTYPE doc [\n"
10228         "  <!ENTITY e SYSTEM 'foo'>\n"
10229         "]>\n"
10230         "<doc>&e;</doc>";
10231     char entity_text[] = "Hello world";
10232     const XML_Char *base =
10233         /* 64 characters per line */
10234         XCS("LongBaseURI/that/will/overflow/an/internal/buffer/and/cause/it/t")
10235         XCS("o/have/to/grow/PQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
10236         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
10237         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
10238         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
10239         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
10240         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
10241         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
10242         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
10243         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
10244         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
10245         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
10246         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
10247         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
10248         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
10249         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/");
10250     int i;
10251     const int max_alloc_count = 25;
10252 
10253     for (i = 0; i < max_alloc_count; i++) {
10254         allocation_count = i;
10255         XML_SetUserData(parser, entity_text);
10256         XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
10257         XML_SetExternalEntityRefHandler(parser, external_entity_alloc);
10258         if (XML_SetBase(parser, base) == XML_STATUS_ERROR) {
10259             XML_ParserReset(parser, NULL);
10260             continue;
10261         }
10262         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
10263                                     XML_TRUE) != XML_STATUS_ERROR)
10264             break;
10265         /* See comment in test_alloc_parse_xdecl() */
10266         alloc_teardown();
10267         alloc_setup();
10268     }
10269     if (i == 0)
10270         fail("Parsing worked despite failing allocations");
10271     else if (i == max_alloc_count)
10272         fail("Parsing failed even at max allocation count");
10273 }
10274 END_TEST
10275 
START_TEST(test_alloc_long_public_id)10276 START_TEST(test_alloc_long_public_id)
10277 {
10278     const char *text =
10279         "<!DOCTYPE doc [\n"
10280         "  <!ENTITY e PUBLIC '"
10281         /* 64 characters per line */
10282         "LongPublicIDThatShouldResultInAnInternalStringPoolGrowingAtASpec"
10283         "ificMomentKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10284         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10285         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10286         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10287         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10288         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10289         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10290         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10291         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10292         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10293         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10294         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10295         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10296         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10297         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10298         "' 'bar'>\n"
10299         "]>\n"
10300         "<doc>&e;</doc>";
10301     char entity_text[] = "Hello world";
10302     int i;
10303     const int max_alloc_count = 40;
10304 
10305     for (i = 0; i < max_alloc_count; i++) {
10306         allocation_count = i;
10307         XML_SetUserData(parser, entity_text);
10308         XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
10309         XML_SetExternalEntityRefHandler(parser, external_entity_alloc);
10310         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
10311                                     XML_TRUE) != XML_STATUS_ERROR)
10312             break;
10313         /* See comment in test_alloc_parse_xdecl() */
10314         alloc_teardown();
10315         alloc_setup();
10316     }
10317     if (i == 0)
10318         fail("Parsing worked despite failing allocations");
10319     else if (i == max_alloc_count)
10320         fail("Parsing failed even at max allocation count");
10321 }
10322 END_TEST
10323 
START_TEST(test_alloc_long_entity_value)10324 START_TEST(test_alloc_long_entity_value)
10325 {
10326     const char *text =
10327         "<!DOCTYPE doc [\n"
10328         "  <!ENTITY e1 '"
10329         /* 64 characters per line */
10330         "Long entity value that should provoke a string pool to grow whil"
10331         "e setting up to parse the external entity below. xyz0123456789AB"
10332         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10333         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10334         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10335         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10336         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10337         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10338         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10339         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10340         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10341         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10342         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10343         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10344         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10345         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10346         "'>\n"
10347         "  <!ENTITY e2 SYSTEM 'bar'>\n"
10348         "]>\n"
10349         "<doc>&e2;</doc>";
10350     char entity_text[] = "Hello world";
10351     int i;
10352     const int max_alloc_count = 40;
10353 
10354     for (i = 0; i < max_alloc_count; i++) {
10355         allocation_count = i;
10356         XML_SetUserData(parser, entity_text);
10357         XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
10358         XML_SetExternalEntityRefHandler(parser, external_entity_alloc);
10359         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
10360                                     XML_TRUE) != XML_STATUS_ERROR)
10361             break;
10362         /* See comment in test_alloc_parse_xdecl() */
10363         alloc_teardown();
10364         alloc_setup();
10365     }
10366     if (i == 0)
10367         fail("Parsing worked despite failing allocations");
10368     else if (i == max_alloc_count)
10369         fail("Parsing failed even at max allocation count");
10370 }
10371 END_TEST
10372 
START_TEST(test_alloc_long_notation)10373 START_TEST(test_alloc_long_notation)
10374 {
10375     const char *text =
10376         "<!DOCTYPE doc [\n"
10377         "  <!NOTATION note SYSTEM '"
10378         /* 64 characters per line */
10379         "ALongNotationNameThatShouldProvokeStringPoolGrowthWhileCallingAn"
10380         "ExternalEntityParserUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10381         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10382         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10383         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10384         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10385         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10386         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10387         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10388         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10389         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10390         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10391         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10392         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10393         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10394         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10395         "'>\n"
10396         "  <!ENTITY e1 SYSTEM 'foo' NDATA "
10397         /* 64 characters per line */
10398         "ALongNotationNameThatShouldProvokeStringPoolGrowthWhileCallingAn"
10399         "ExternalEntityParserUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10400         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10401         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10402         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10403         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10404         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10405         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10406         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10407         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10408         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10409         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10410         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10411         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10412         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10413         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10414         ">\n"
10415         "  <!ENTITY e2 SYSTEM 'bar'>\n"
10416         "]>\n"
10417         "<doc>&e2;</doc>";
10418     ExtOption options[] = {
10419         { XCS("foo"), "Entity Foo" },
10420         { XCS("bar"), "Entity Bar" },
10421         { NULL, NULL }
10422     };
10423     int i;
10424     const int max_alloc_count = 40;
10425 
10426     for (i = 0; i < max_alloc_count; i++) {
10427         allocation_count = i;
10428         XML_SetUserData(parser, options);
10429         XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
10430         XML_SetExternalEntityRefHandler(parser, external_entity_optioner);
10431         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
10432                                     XML_TRUE) != XML_STATUS_ERROR)
10433             break;
10434 
10435         /* See comment in test_alloc_parse_xdecl() */
10436         alloc_teardown();
10437         alloc_setup();
10438     }
10439     if (i == 0)
10440         fail("Parsing worked despite failing allocations");
10441     else if (i == max_alloc_count)
10442         fail("Parsing failed even at max allocation count");
10443 }
10444 END_TEST
10445 
10446 
10447 static void
nsalloc_setup(void)10448 nsalloc_setup(void)
10449 {
10450     XML_Memory_Handling_Suite memsuite = {
10451         duff_allocator,
10452         duff_reallocator,
10453         free
10454     };
10455     XML_Char ns_sep[2] = { ' ', '\0' };
10456 
10457     /* Ensure the parser creation will go through */
10458     allocation_count = ALLOC_ALWAYS_SUCCEED;
10459     reallocation_count = REALLOC_ALWAYS_SUCCEED;
10460     parser = XML_ParserCreate_MM(NULL, &memsuite, ns_sep);
10461     if (parser == NULL)
10462         fail("Parser not created");
10463 }
10464 
10465 static void
nsalloc_teardown(void)10466 nsalloc_teardown(void)
10467 {
10468     basic_teardown();
10469 }
10470 
10471 
10472 /* Test the effects of allocation failure in simple namespace parsing.
10473  * Based on test_ns_default_with_empty_uri()
10474  */
START_TEST(test_nsalloc_xmlns)10475 START_TEST(test_nsalloc_xmlns)
10476 {
10477     const char *text =
10478         "<doc xmlns='http://example.org/'>\n"
10479         "  <e xmlns=''/>\n"
10480         "</doc>";
10481     unsigned int i;
10482     const unsigned int max_alloc_count = 30;
10483 
10484     for (i = 0; i < max_alloc_count; i++) {
10485         allocation_count = i;
10486         /* Exercise more code paths with a default handler */
10487         XML_SetDefaultHandler(parser, dummy_default_handler);
10488         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
10489                                     XML_TRUE) != XML_STATUS_ERROR)
10490             break;
10491         /* Resetting the parser is insufficient, because some memory
10492          * allocations are cached within the parser.  Instead we use
10493          * the teardown and setup routines to ensure that we have the
10494          * right sort of parser back in our hands.
10495          */
10496         nsalloc_teardown();
10497         nsalloc_setup();
10498     }
10499     if (i == 0)
10500         fail("Parsing worked despite failing allocations");
10501     else if (i == max_alloc_count)
10502         fail("Parsing failed even at maximum allocation count");
10503 }
10504 END_TEST
10505 
10506 /* Test XML_ParseBuffer interface with namespace and a dicky allocator */
START_TEST(test_nsalloc_parse_buffer)10507 START_TEST(test_nsalloc_parse_buffer)
10508 {
10509     const char *text = "<doc>Hello</doc>";
10510     void *buffer;
10511 
10512     /* Try a parse before the start of the world */
10513     /* (Exercises new code path) */
10514     allocation_count = 0;
10515     if (XML_ParseBuffer(parser, 0, XML_FALSE) != XML_STATUS_ERROR)
10516         fail("Pre-init XML_ParseBuffer not faulted");
10517     if (XML_GetErrorCode(parser) != XML_ERROR_NO_MEMORY)
10518         fail("Pre-init XML_ParseBuffer faulted for wrong reason");
10519 
10520     /* Now with actual memory allocation */
10521     allocation_count = ALLOC_ALWAYS_SUCCEED;
10522     if (XML_ParseBuffer(parser, 0, XML_FALSE) != XML_STATUS_OK)
10523         xml_failure(parser);
10524 
10525     /* Check that resuming an unsuspended parser is faulted */
10526     if (XML_ResumeParser(parser) != XML_STATUS_ERROR)
10527         fail("Resuming unsuspended parser not faulted");
10528     if (XML_GetErrorCode(parser) != XML_ERROR_NOT_SUSPENDED)
10529         xml_failure(parser);
10530 
10531     /* Get the parser into suspended state */
10532     XML_SetCharacterDataHandler(parser, clearing_aborting_character_handler);
10533     resumable = XML_TRUE;
10534     buffer = XML_GetBuffer(parser, strlen(text));
10535     if (buffer == NULL)
10536         fail("Could not acquire parse buffer");
10537     memcpy(buffer, text, strlen(text));
10538     if (XML_ParseBuffer(parser, strlen(text),
10539                         XML_TRUE) != XML_STATUS_SUSPENDED)
10540         xml_failure(parser);
10541     if (XML_GetErrorCode(parser) != XML_ERROR_NONE)
10542         xml_failure(parser);
10543     if (XML_ParseBuffer(parser, strlen(text), XML_TRUE) != XML_STATUS_ERROR)
10544         fail("Suspended XML_ParseBuffer not faulted");
10545     if (XML_GetErrorCode(parser) != XML_ERROR_SUSPENDED)
10546         xml_failure(parser);
10547     if (XML_GetBuffer(parser, strlen(text)) != NULL)
10548         fail("Suspended XML_GetBuffer not faulted");
10549 
10550     /* Get it going again and complete the world */
10551     XML_SetCharacterDataHandler(parser, NULL);
10552     if (XML_ResumeParser(parser) != XML_STATUS_OK)
10553         xml_failure(parser);
10554     if (XML_ParseBuffer(parser, strlen(text), XML_TRUE) != XML_STATUS_ERROR)
10555         fail("Post-finishing XML_ParseBuffer not faulted");
10556     if (XML_GetErrorCode(parser) != XML_ERROR_FINISHED)
10557         xml_failure(parser);
10558     if (XML_GetBuffer(parser, strlen(text)) != NULL)
10559         fail("Post-finishing XML_GetBuffer not faulted");
10560 }
10561 END_TEST
10562 
10563 /* Check handling of long prefix names (pool growth) */
START_TEST(test_nsalloc_long_prefix)10564 START_TEST(test_nsalloc_long_prefix)
10565 {
10566     const char *text =
10567         "<"
10568         /* 64 characters per line */
10569         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10570         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10571         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10572         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10573         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10574         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10575         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10576         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10577         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10578         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10579         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10580         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10581         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10582         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10583         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10584         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10585         ":foo xmlns:"
10586         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10587         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10588         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10589         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10590         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10591         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10592         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10593         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10594         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10595         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10596         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10597         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10598         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10599         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10600         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10601         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10602         "='http://example.org/'>"
10603         "</"
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         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10617         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10618         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10619         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10620         ":foo>";
10621     int i;
10622     const int max_alloc_count = 40;
10623 
10624     for (i = 0; i < max_alloc_count; i++) {
10625         allocation_count = i;
10626         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
10627                                     XML_TRUE) != XML_STATUS_ERROR)
10628             break;
10629         /* See comment in test_nsalloc_xmlns() */
10630         nsalloc_teardown();
10631         nsalloc_setup();
10632     }
10633     if (i == 0)
10634         fail("Parsing worked despite failing allocations");
10635     else if (i == max_alloc_count)
10636         fail("Parsing failed even at max allocation count");
10637 }
10638 END_TEST
10639 
10640 /* Check handling of long uri names (pool growth) */
START_TEST(test_nsalloc_long_uri)10641 START_TEST(test_nsalloc_long_uri)
10642 {
10643     const char *text =
10644         "<foo:e xmlns:foo='http://example.org/"
10645         /* 64 characters per line */
10646         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10647         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10648         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10649         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10650         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10651         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10652         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10653         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10654         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10655         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10656         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10657         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10658         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10659         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10660         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10661         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10662         "' bar:a='12'\n"
10663         "xmlns:bar='http://example.org/"
10664         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10665         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10666         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10667         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10668         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10669         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10670         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10671         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10672         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10673         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10674         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10675         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10676         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10677         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10678         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10679         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10680         "'>"
10681         "</foo:e>";
10682     int i;
10683     const int max_alloc_count = 40;
10684 
10685     for (i = 0; i < max_alloc_count; i++) {
10686         allocation_count = i;
10687         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
10688                                     XML_TRUE) != XML_STATUS_ERROR)
10689             break;
10690         /* See comment in test_nsalloc_xmlns() */
10691         nsalloc_teardown();
10692         nsalloc_setup();
10693     }
10694     if (i == 0)
10695         fail("Parsing worked despite failing allocations");
10696     else if (i == max_alloc_count)
10697         fail("Parsing failed even at max allocation count");
10698 }
10699 END_TEST
10700 
10701 /* Test handling of long attribute names with prefixes */
START_TEST(test_nsalloc_long_attr)10702 START_TEST(test_nsalloc_long_attr)
10703 {
10704     const char *text =
10705         "<foo:e xmlns:foo='http://example.org/' bar:"
10706         /* 64 characters per line */
10707         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10708         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10709         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10710         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
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         "='12'\n"
10724         "xmlns:bar='http://example.org/'>"
10725         "</foo:e>";
10726     int i;
10727     const int max_alloc_count = 40;
10728 
10729     for (i = 0; i < max_alloc_count; i++) {
10730         allocation_count = i;
10731         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
10732                                     XML_TRUE) != XML_STATUS_ERROR)
10733             break;
10734         /* See comment in test_nsalloc_xmlns() */
10735         nsalloc_teardown();
10736         nsalloc_setup();
10737     }
10738     if (i == 0)
10739         fail("Parsing worked despite failing allocations");
10740     else if (i == max_alloc_count)
10741         fail("Parsing failed even at max allocation count");
10742 }
10743 END_TEST
10744 
10745 /* Test handling of an attribute name with a long namespace prefix */
START_TEST(test_nsalloc_long_attr_prefix)10746 START_TEST(test_nsalloc_long_attr_prefix)
10747 {
10748     const char *text =
10749         "<foo:e xmlns:foo='http://example.org/' "
10750         /* 64 characters per line */
10751         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10752         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10753         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10754         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10755         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10756         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10757         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10758         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10759         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10760         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10761         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10762         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10763         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10764         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10765         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10766         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10767         ":a='12'\n"
10768         "xmlns:"
10769         /* 64 characters per line */
10770         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10771         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10772         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10773         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10774         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10775         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10776         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10777         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10778         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10779         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10780         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10781         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10782         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10783         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10784         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10785         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10786         "='http://example.org/'>"
10787         "</foo:e>";
10788     const XML_Char *elemstr[] = {
10789         XCS("http://example.org/ e foo"),
10790         XCS("http://example.org/ a ")
10791         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10792         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10793         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10794         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10795         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10796         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10797         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10798         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10799         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10800         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10801         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10802         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10803         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10804         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10805         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10806         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10807     };
10808     int i;
10809     const int max_alloc_count = 40;
10810 
10811     for (i = 0; i < max_alloc_count; i++) {
10812         allocation_count = i;
10813         XML_SetReturnNSTriplet(parser, XML_TRUE);
10814         XML_SetUserData(parser, elemstr);
10815         XML_SetElementHandler(parser,
10816                               triplet_start_checker,
10817                               triplet_end_checker);
10818         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
10819                                     XML_TRUE) != XML_STATUS_ERROR)
10820             break;
10821         /* See comment in test_nsalloc_xmlns() */
10822         nsalloc_teardown();
10823         nsalloc_setup();
10824     }
10825     if (i == 0)
10826         fail("Parsing worked despite failing allocations");
10827     else if (i == max_alloc_count)
10828         fail("Parsing failed even at max allocation count");
10829 }
10830 END_TEST
10831 
10832 /* Test attribute handling in the face of a dodgy reallocator */
START_TEST(test_nsalloc_realloc_attributes)10833 START_TEST(test_nsalloc_realloc_attributes)
10834 {
10835     const char *text =
10836         "<foo:e xmlns:foo='http://example.org/' bar:a='12'\n"
10837         "       xmlns:bar='http://example.org/'>"
10838         "</foo:e>";
10839     int i;
10840     const int max_realloc_count = 10;
10841 
10842     for (i = 0; i < max_realloc_count; i++) {
10843         reallocation_count = i;
10844         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
10845                                     XML_TRUE) != XML_STATUS_ERROR)
10846             break;
10847         /* See comment in test_nsalloc_xmlns() */
10848         nsalloc_teardown();
10849         nsalloc_setup();
10850     }
10851     if (i == 0)
10852         fail("Parsing worked despite failing reallocations");
10853     else if (i == max_realloc_count)
10854         fail("Parsing failed at max reallocation count");
10855 }
10856 END_TEST
10857 
10858 /* Test long element names with namespaces under a failing allocator */
START_TEST(test_nsalloc_long_element)10859 START_TEST(test_nsalloc_long_element)
10860 {
10861     const char *text =
10862         "<foo:thisisalongenoughelementnametotriggerareallocation\n"
10863         " xmlns:foo='http://example.org/' bar:a='12'\n"
10864         " xmlns:bar='http://example.org/'>"
10865         "</foo:thisisalongenoughelementnametotriggerareallocation>";
10866     const XML_Char *elemstr[] = {
10867         XCS("http://example.org/")
10868         XCS(" thisisalongenoughelementnametotriggerareallocation foo"),
10869         XCS("http://example.org/ a bar")
10870     };
10871     int i;
10872     const int max_alloc_count = 30;
10873 
10874     for (i = 0; i < max_alloc_count; i++) {
10875         allocation_count = i;
10876         XML_SetReturnNSTriplet(parser, XML_TRUE);
10877         XML_SetUserData(parser, elemstr);
10878         XML_SetElementHandler(parser,
10879                               triplet_start_checker,
10880                               triplet_end_checker);
10881         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
10882                                     XML_TRUE) != XML_STATUS_ERROR)
10883             break;
10884         /* See comment in test_nsalloc_xmlns() */
10885         nsalloc_teardown();
10886         nsalloc_setup();
10887     }
10888     if (i == 0)
10889         fail("Parsing worked despite failing reallocations");
10890     else if (i == max_alloc_count)
10891         fail("Parsing failed at max reallocation count");
10892 }
10893 END_TEST
10894 
10895 /* Test the effects of reallocation failure when reassigning a
10896  * binding.
10897  *
10898  * XML_ParserReset does not free the BINDING structures used by a
10899  * parser, but instead adds them to an internal free list to be reused
10900  * as necessary.  Likewise the URI buffers allocated for the binding
10901  * aren't freed, but kept attached to their existing binding.  If the
10902  * new binding has a longer URI, it will need reallocation.  This test
10903  * provokes that reallocation, and tests the control path if it fails.
10904  */
START_TEST(test_nsalloc_realloc_binding_uri)10905 START_TEST(test_nsalloc_realloc_binding_uri)
10906 {
10907     const char *first =
10908         "<doc xmlns='http://example.org/'>\n"
10909         "  <e xmlns='' />\n"
10910         "</doc>";
10911     const char *second =
10912         "<doc xmlns='http://example.org/long/enough/URI/to/reallocate/'>\n"
10913         "  <e xmlns='' />\n"
10914         "</doc>";
10915     unsigned i;
10916     const unsigned max_realloc_count = 10;
10917 
10918     /* First, do a full parse that will leave bindings around */
10919     if (_XML_Parse_SINGLE_BYTES(parser, first, strlen(first),
10920                                 XML_TRUE) == XML_STATUS_ERROR)
10921         xml_failure(parser);
10922 
10923     /* Now repeat with a longer URI and a duff reallocator */
10924     for (i = 0; i < max_realloc_count; i++) {
10925         XML_ParserReset(parser, NULL);
10926         reallocation_count = i;
10927         if (_XML_Parse_SINGLE_BYTES(parser, second, strlen(second),
10928                                     XML_TRUE) != XML_STATUS_ERROR)
10929             break;
10930     }
10931     if (i == 0)
10932         fail("Parsing worked despite failing reallocation");
10933     else if (i == max_realloc_count)
10934         fail("Parsing failed at max reallocation count");
10935 }
10936 END_TEST
10937 
10938 /* Check handling of long prefix names (pool growth) */
START_TEST(test_nsalloc_realloc_long_prefix)10939 START_TEST(test_nsalloc_realloc_long_prefix)
10940 {
10941     const char *text =
10942         "<"
10943         /* 64 characters per line */
10944         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10945         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10946         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10947         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10948         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10949         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10950         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10951         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10952         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10953         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10954         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10955         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10956         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10957         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10958         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10959         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10960         ":foo xmlns:"
10961         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10962         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10963         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10964         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10965         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10966         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10967         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10968         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10969         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10970         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10971         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10972         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10973         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10974         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10975         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10976         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10977         "='http://example.org/'>"
10978         "</"
10979         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10980         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10981         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10982         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10983         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10984         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10985         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10986         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10987         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10988         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10989         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10990         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10991         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10992         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10993         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10994         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10995         ":foo>";
10996     int i;
10997     const int max_realloc_count = 12;
10998 
10999     for (i = 0; i < max_realloc_count; i++) {
11000         reallocation_count = i;
11001         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
11002                                     XML_TRUE) != XML_STATUS_ERROR)
11003             break;
11004         /* See comment in test_nsalloc_xmlns() */
11005         nsalloc_teardown();
11006         nsalloc_setup();
11007     }
11008     if (i == 0)
11009         fail("Parsing worked despite failing reallocations");
11010     else if (i == max_realloc_count)
11011         fail("Parsing failed even at max reallocation count");
11012 }
11013 END_TEST
11014 
11015 /* Check handling of even long prefix names (different code path) */
START_TEST(test_nsalloc_realloc_longer_prefix)11016 START_TEST(test_nsalloc_realloc_longer_prefix)
11017 {
11018     const char *text =
11019         "<"
11020         /* 64 characters per line */
11021         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11022         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11023         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11024         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11025         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11026         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11027         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11028         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11029         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11030         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11031         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11032         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11033         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11034         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11035         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11036         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11037         "Q:foo xmlns:"
11038         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11039         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11040         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11041         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11042         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11043         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11044         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11045         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11046         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11047         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11048         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11049         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11050         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11051         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11052         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11053         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11054         "Q='http://example.org/'>"
11055         "</"
11056         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11057         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11058         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11059         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11060         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11061         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11062         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11063         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11064         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11065         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11066         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11067         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11068         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11069         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11070         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11071         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11072         "Q:foo>";
11073     int i;
11074     const int max_realloc_count = 12;
11075 
11076     for (i = 0; i < max_realloc_count; i++) {
11077         reallocation_count = i;
11078         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
11079                                     XML_TRUE) != XML_STATUS_ERROR)
11080             break;
11081         /* See comment in test_nsalloc_xmlns() */
11082         nsalloc_teardown();
11083         nsalloc_setup();
11084     }
11085     if (i == 0)
11086         fail("Parsing worked despite failing reallocations");
11087     else if (i == max_realloc_count)
11088         fail("Parsing failed even at max reallocation count");
11089 }
11090 END_TEST
11091 
START_TEST(test_nsalloc_long_namespace)11092 START_TEST(test_nsalloc_long_namespace)
11093 {
11094     const char *text1 =
11095         "<"
11096         /* 64 characters per line */
11097         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11098         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11099         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11100         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11101         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11102         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11103         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11104         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11105         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11106         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11107         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11108         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11109         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11110         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11111         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11112         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11113         ":e xmlns:"
11114         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11115         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11116         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11117         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11118         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11119         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11120         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11121         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11122         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11123         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11124         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11125         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11126         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11127         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11128         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11129         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11130         "='http://example.org/'>\n";
11131     const char *text2 =
11132         "<"
11133         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11134         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11135         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11136         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11137         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11138         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11139         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11140         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11141         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11142         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11143         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11144         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11145         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11146         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11147         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11148         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11149         ":f "
11150         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11151         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11152         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11153         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11154         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11155         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11156         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11157         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11158         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11159         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11160         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11161         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11162         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11163         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11164         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11165         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11166         ":attr='foo'/>\n"
11167         "</"
11168         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11169         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11170         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11171         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11172         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11173         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11174         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11175         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11176         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11177         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11178         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11179         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11180         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11181         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11182         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11183         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11184         ":e>";
11185     int i;
11186     const int max_alloc_count = 40;
11187 
11188     for (i = 0; i < max_alloc_count; i++) {
11189         allocation_count = i;
11190         if (_XML_Parse_SINGLE_BYTES(parser, text1, strlen(text1),
11191                                     XML_FALSE) != XML_STATUS_ERROR &&
11192             _XML_Parse_SINGLE_BYTES(parser, text2, strlen(text2),
11193                                     XML_TRUE) != XML_STATUS_ERROR)
11194             break;
11195         /* See comment in test_nsalloc_xmlns() */
11196         nsalloc_teardown();
11197         nsalloc_setup();
11198     }
11199     if (i == 0)
11200         fail("Parsing worked despite failing allocations");
11201     else if (i == max_alloc_count)
11202         fail("Parsing failed even at max allocation count");
11203 }
11204 END_TEST
11205 
11206 /* Using a slightly shorter namespace name provokes allocations in
11207  * slightly different places in the code.
11208  */
START_TEST(test_nsalloc_less_long_namespace)11209 START_TEST(test_nsalloc_less_long_namespace)
11210 {
11211     const char *text =
11212         "<"
11213         /* 64 characters per line */
11214         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11215         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11216         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11217         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11218         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11219         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11220         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11221         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
11222         ":e xmlns:"
11223         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11224         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11225         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11226         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11227         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11228         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11229         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11230         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
11231         "='http://example.org/'>\n"
11232         "<"
11233         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11234         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11235         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11236         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11237         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11238         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11239         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11240         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
11241         ":f "
11242         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11243         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11244         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11245         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11246         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11247         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11248         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11249         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
11250         ":att='foo'/>\n"
11251         "</"
11252         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11253         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11254         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11255         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11256         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11257         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11258         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11259         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
11260         ":e>";
11261     int i;
11262     const int max_alloc_count = 40;
11263 
11264     for (i = 0; i < max_alloc_count; i++) {
11265         allocation_count = i;
11266         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
11267                                     XML_TRUE) != XML_STATUS_ERROR)
11268             break;
11269         /* See comment in test_nsalloc_xmlns() */
11270         nsalloc_teardown();
11271         nsalloc_setup();
11272     }
11273     if (i == 0)
11274         fail("Parsing worked despite failing allocations");
11275     else if (i == max_alloc_count)
11276         fail("Parsing failed even at max allocation count");
11277 }
11278 END_TEST
11279 
START_TEST(test_nsalloc_long_context)11280 START_TEST(test_nsalloc_long_context)
11281 {
11282     const char *text =
11283         "<!DOCTYPE doc SYSTEM 'foo' [\n"
11284         "  <!ATTLIST doc baz ID #REQUIRED>\n"
11285         "  <!ENTITY en SYSTEM 'bar'>\n"
11286         "]>\n"
11287         "<doc xmlns='http://example.org/"
11288         /* 64 characters per line */
11289         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11290         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11291         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11292         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11293         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11294         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11295         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11296         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11297         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11298         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11299         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11300         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11301         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11302         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11303         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11304         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKL"
11305         "' baz='2'>\n"
11306         "&en;"
11307         "</doc>";
11308     ExtOption options[] = {
11309         { XCS("foo"), "<!ELEMENT e EMPTY>"},
11310         { XCS("bar"), "<e/>" },
11311         { NULL, NULL }
11312     };
11313     int i;
11314     const int max_alloc_count = 70;
11315 
11316     for (i = 0; i < max_alloc_count; i++) {
11317         allocation_count = i;
11318         XML_SetUserData(parser, options);
11319         XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11320         XML_SetExternalEntityRefHandler(parser, external_entity_optioner);
11321         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
11322                                     XML_TRUE) != XML_STATUS_ERROR)
11323             break;
11324 
11325         /* See comment in test_nsalloc_xmlns() */
11326         nsalloc_teardown();
11327         nsalloc_setup();
11328     }
11329     if (i == 0)
11330         fail("Parsing worked despite failing allocations");
11331     else if (i == max_alloc_count)
11332         fail("Parsing failed even at max allocation count");
11333 }
11334 END_TEST
11335 
11336 /* This function is void; it will throw a fail() on error, so if it
11337  * returns normally it must have succeeded.
11338  */
11339 static void
context_realloc_test(const char * text)11340 context_realloc_test(const char *text)
11341 {
11342     ExtOption options[] = {
11343         { XCS("foo"), "<!ELEMENT e EMPTY>"},
11344         { XCS("bar"), "<e/>" },
11345         { NULL, NULL }
11346     };
11347     int i;
11348     const int max_realloc_count = 6;
11349 
11350     for (i = 0; i < max_realloc_count; i++) {
11351         reallocation_count = i;
11352         XML_SetUserData(parser, options);
11353         XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11354         XML_SetExternalEntityRefHandler(parser, external_entity_optioner);
11355         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
11356                                     XML_TRUE) != XML_STATUS_ERROR)
11357             break;
11358         /* See comment in test_nsalloc_xmlns() */
11359         nsalloc_teardown();
11360         nsalloc_setup();
11361     }
11362     if (i == 0)
11363         fail("Parsing worked despite failing reallocations");
11364     else if (i == max_realloc_count)
11365         fail("Parsing failed even at max reallocation count");
11366 }
11367 
START_TEST(test_nsalloc_realloc_long_context)11368 START_TEST(test_nsalloc_realloc_long_context)
11369 {
11370     const char *text =
11371         "<!DOCTYPE doc SYSTEM 'foo' [\n"
11372         "  <!ENTITY en SYSTEM 'bar'>\n"
11373         "]>\n"
11374         "<doc xmlns='http://example.org/"
11375         /* 64 characters per line */
11376         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11377         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11378         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11379         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11380         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11381         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11382         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11383         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
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/ABCDEFGHIJKL"
11392         "'>\n"
11393         "&en;"
11394         "</doc>";
11395 
11396     context_realloc_test(text);
11397 }
11398 END_TEST
11399 
START_TEST(test_nsalloc_realloc_long_context_2)11400 START_TEST(test_nsalloc_realloc_long_context_2)
11401 {
11402     const char *text =
11403         "<!DOCTYPE doc SYSTEM 'foo' [\n"
11404         "  <!ENTITY en SYSTEM 'bar'>\n"
11405         "]>\n"
11406         "<doc xmlns='http://example.org/"
11407         /* 64 characters per line */
11408         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11409         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11410         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11411         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11412         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11413         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11414         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11415         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11416         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11417         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11418         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11419         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11420         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11421         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11422         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11423         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJK"
11424         "'>\n"
11425         "&en;"
11426         "</doc>";
11427 
11428     context_realloc_test(text);
11429 }
11430 END_TEST
11431 
START_TEST(test_nsalloc_realloc_long_context_3)11432 START_TEST(test_nsalloc_realloc_long_context_3)
11433 {
11434     const char *text =
11435         "<!DOCTYPE doc SYSTEM 'foo' [\n"
11436         "  <!ENTITY en SYSTEM 'bar'>\n"
11437         "]>\n"
11438         "<doc xmlns='http://example.org/"
11439         /* 64 characters per line */
11440         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11441         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11442         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11443         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11444         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11445         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11446         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11447         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11448         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11449         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11450         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11451         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11452         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11453         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11454         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11455         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGH"
11456         "'>\n"
11457         "&en;"
11458         "</doc>";
11459 
11460     context_realloc_test(text);
11461 }
11462 END_TEST
11463 
START_TEST(test_nsalloc_realloc_long_context_4)11464 START_TEST(test_nsalloc_realloc_long_context_4)
11465 {
11466     const char *text =
11467         "<!DOCTYPE doc SYSTEM 'foo' [\n"
11468         "  <!ENTITY en SYSTEM 'bar'>\n"
11469         "]>\n"
11470         "<doc xmlns='http://example.org/"
11471         /* 64 characters per line */
11472         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11473         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11474         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11475         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11476         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11477         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11478         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11479         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11480         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11481         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11482         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11483         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11484         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11485         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11486         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11487         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO"
11488         "'>\n"
11489         "&en;"
11490         "</doc>";
11491 
11492     context_realloc_test(text);
11493 }
11494 END_TEST
11495 
START_TEST(test_nsalloc_realloc_long_context_5)11496 START_TEST(test_nsalloc_realloc_long_context_5)
11497 {
11498     const char *text =
11499         "<!DOCTYPE doc SYSTEM 'foo' [\n"
11500         "  <!ENTITY en SYSTEM 'bar'>\n"
11501         "]>\n"
11502         "<doc xmlns='http://example.org/"
11503         /* 64 characters per line */
11504         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11505         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11506         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11507         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11508         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11509         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11510         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11511         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11512         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11513         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11514         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11515         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11516         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11517         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11518         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11519         "ABC"
11520         "'>\n"
11521         "&en;"
11522         "</doc>";
11523 
11524     context_realloc_test(text);
11525 }
11526 END_TEST
11527 
START_TEST(test_nsalloc_realloc_long_context_6)11528 START_TEST(test_nsalloc_realloc_long_context_6)
11529 {
11530     const char *text =
11531         "<!DOCTYPE doc SYSTEM 'foo' [\n"
11532         "  <!ENTITY en SYSTEM 'bar'>\n"
11533         "]>\n"
11534         "<doc xmlns='http://example.org/"
11535         /* 64 characters per line */
11536         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11537         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11538         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11539         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11540         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11541         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11542         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11543         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11544         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11545         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11546         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11547         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11548         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11549         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11550         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
11551         "'>\n"
11552         "&en;"
11553         "</doc>";
11554 
11555     context_realloc_test(text);
11556 }
11557 END_TEST
11558 
START_TEST(test_nsalloc_realloc_long_context_7)11559 START_TEST(test_nsalloc_realloc_long_context_7)
11560 {
11561     const char *text =
11562         "<!DOCTYPE doc SYSTEM 'foo' [\n"
11563         "  <!ENTITY en SYSTEM 'bar'>\n"
11564         "]>\n"
11565         "<doc xmlns='http://example.org/"
11566         /* 64 characters per line */
11567         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11568         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11569         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11570         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11571         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11572         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11573         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11574         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11575         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11576         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11577         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11578         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11579         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11580         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11581         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11582         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLM"
11583         "'>\n"
11584         "&en;"
11585         "</doc>";
11586 
11587     context_realloc_test(text);
11588 }
11589 END_TEST
11590 
START_TEST(test_nsalloc_realloc_long_ge_name)11591 START_TEST(test_nsalloc_realloc_long_ge_name)
11592 {
11593     const char *text =
11594         "<!DOCTYPE doc SYSTEM 'foo' [\n"
11595         "  <!ENTITY "
11596         /* 64 characters per line */
11597         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11598         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11599         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11600         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11601         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11602         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11603         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11604         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11605         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11606         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11607         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11608         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11609         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11610         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11611         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11612         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11613         " SYSTEM 'bar'>\n"
11614         "]>\n"
11615         "<doc xmlns='http://example.org/baz'>\n"
11616         "&"
11617         /* 64 characters per line */
11618         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11619         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11620         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11621         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11622         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11623         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11624         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11625         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11626         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11627         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11628         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11629         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11630         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11631         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11632         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11633         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11634         ";"
11635         "</doc>";
11636     ExtOption options[] = {
11637         { XCS("foo"), "<!ELEMENT el EMPTY>" },
11638         { XCS("bar"), "<el/>" },
11639         { NULL, NULL }
11640     };
11641     int i;
11642     const int max_realloc_count = 10;
11643 
11644     for (i = 0; i < max_realloc_count; i++) {
11645         reallocation_count = i;
11646         XML_SetUserData(parser, options);
11647         XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11648         XML_SetExternalEntityRefHandler(parser, external_entity_optioner);
11649         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
11650                                     XML_TRUE) != XML_STATUS_ERROR)
11651             break;
11652         /* See comment in test_nsalloc_xmlns() */
11653         nsalloc_teardown();
11654         nsalloc_setup();
11655     }
11656     if (i == 0)
11657         fail("Parsing worked despite failing reallocations");
11658     else if (i == max_realloc_count)
11659         fail("Parsing failed even at max reallocation count");
11660 }
11661 END_TEST
11662 
11663 /* Test that when a namespace is passed through the context mechanism
11664  * to an external entity parser, the parsers handle reallocation
11665  * failures correctly.  The prefix is exactly the right length to
11666  * provoke particular uncommon code paths.
11667  */
START_TEST(test_nsalloc_realloc_long_context_in_dtd)11668 START_TEST(test_nsalloc_realloc_long_context_in_dtd)
11669 {
11670     const char *text1 =
11671         "<!DOCTYPE "
11672         /* 64 characters per line */
11673         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11674         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11675         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11676         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11677         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11678         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11679         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11680         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11681         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11682         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11683         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11684         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11685         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11686         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11687         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11688         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11689         ":doc [\n"
11690         "  <!ENTITY First SYSTEM 'foo/First'>\n"
11691         "]>\n"
11692         "<"
11693         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11694         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11695         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11696         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11697         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11698         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11699         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11700         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11701         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11702         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11703         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11704         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11705         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11706         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11707         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11708         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11709         ":doc xmlns:"
11710         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11711         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11712         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11713         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11714         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11715         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11716         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11717         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11718         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11719         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11720         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11721         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11722         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11723         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11724         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11725         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11726         "='foo/Second'>&First;";
11727     const char *text2 = "</"
11728         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11729         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11730         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11731         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11732         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11733         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11734         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11735         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11736         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11737         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11738         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11739         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11740         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11741         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11742         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11743         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11744         ":doc>";
11745     ExtOption options[] = {
11746         { XCS("foo/First"), "Hello world" },
11747         { NULL, NULL }
11748     };
11749     int i;
11750     const int max_realloc_count = 20;
11751 
11752     for (i = 0; i < max_realloc_count; i++) {
11753         reallocation_count = i;
11754         XML_SetUserData(parser, options);
11755         XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11756         XML_SetExternalEntityRefHandler(parser, external_entity_optioner);
11757         if (_XML_Parse_SINGLE_BYTES(parser, text1, strlen(text1),
11758                                     XML_FALSE) != XML_STATUS_ERROR &&
11759             _XML_Parse_SINGLE_BYTES(parser, text2, strlen(text2),
11760                                     XML_TRUE) != XML_STATUS_ERROR)
11761             break;
11762         /* See comment in test_nsalloc_xmlns() */
11763         nsalloc_teardown();
11764         nsalloc_setup();
11765     }
11766     if (i == 0)
11767         fail("Parsing worked despite failing reallocations");
11768     else if (i == max_realloc_count)
11769         fail("Parsing failed even at max reallocation count");
11770 }
11771 END_TEST
11772 
START_TEST(test_nsalloc_long_default_in_ext)11773 START_TEST(test_nsalloc_long_default_in_ext)
11774 {
11775     const char *text =
11776         "<!DOCTYPE doc [\n"
11777         "  <!ATTLIST e a1 CDATA '"
11778         /* 64 characters per line */
11779         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11780         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11781         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11782         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11783         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11784         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11785         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11786         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11787         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11788         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11789         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11790         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11791         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11792         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11793         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11794         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11795         "'>\n"
11796         "  <!ENTITY x SYSTEM 'foo'>\n"
11797         "]>\n"
11798         "<doc>&x;</doc>";
11799     ExtOption options[] = {
11800         { XCS("foo"), "<e/>"},
11801         { NULL, NULL }
11802     };
11803     int i;
11804     const int max_alloc_count = 50;
11805 
11806     for (i = 0; i < max_alloc_count; i++) {
11807         allocation_count = i;
11808         XML_SetUserData(parser, options);
11809         XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11810         XML_SetExternalEntityRefHandler(parser, external_entity_optioner);
11811         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
11812                                     XML_TRUE) != XML_STATUS_ERROR)
11813             break;
11814 
11815         /* See comment in test_nsalloc_xmlns() */
11816         nsalloc_teardown();
11817         nsalloc_setup();
11818     }
11819     if (i == 0)
11820         fail("Parsing worked despite failing allocations");
11821     else if (i == max_alloc_count)
11822         fail("Parsing failed even at max allocation count");
11823 }
11824 END_TEST
11825 
START_TEST(test_nsalloc_long_systemid_in_ext)11826 START_TEST(test_nsalloc_long_systemid_in_ext)
11827 {
11828     const char *text =
11829         "<!DOCTYPE doc SYSTEM 'foo' [\n"
11830         "  <!ENTITY en SYSTEM '"
11831         /* 64 characters per line */
11832         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11833         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11834         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11835         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11836         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11837         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11838         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11839         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11840         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11841         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11842         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11843         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11844         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11845         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11846         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11847         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11848         "'>\n"
11849         "]>\n"
11850         "<doc>&en;</doc>";
11851     ExtOption options[] = {
11852         { XCS("foo"), "<!ELEMENT e EMPTY>" },
11853         {
11854             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11855             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11856             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11857             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11858             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11859             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11860             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11861             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11862             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11863             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11864             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11865             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11866             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11867             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11868             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11869             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"),
11870             "<e/>"
11871         },
11872         { NULL, NULL }
11873     };
11874     int i;
11875     const int max_alloc_count = 55;
11876 
11877     for (i = 0; i < max_alloc_count; i++) {
11878         allocation_count = i;
11879         XML_SetUserData(parser, options);
11880         XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11881         XML_SetExternalEntityRefHandler(parser, external_entity_optioner);
11882         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
11883                                     XML_TRUE) != XML_STATUS_ERROR)
11884             break;
11885 
11886         /* See comment in test_nsalloc_xmlns() */
11887         nsalloc_teardown();
11888         nsalloc_setup();
11889     }
11890     if (i == 0)
11891         fail("Parsing worked despite failing allocations");
11892     else if (i == max_alloc_count)
11893         fail("Parsing failed even at max allocation count");
11894 }
11895 END_TEST
11896 
11897 /* Test the effects of allocation failure on parsing an element in a
11898  * namespace.  Based on test_nsalloc_long_context.
11899  */
START_TEST(test_nsalloc_prefixed_element)11900 START_TEST(test_nsalloc_prefixed_element)
11901 {
11902     const char *text =
11903         "<!DOCTYPE pfx:element SYSTEM 'foo' [\n"
11904         "  <!ATTLIST pfx:element baz ID #REQUIRED>\n"
11905         "  <!ENTITY en SYSTEM 'bar'>\n"
11906         "]>\n"
11907         "<pfx:element xmlns:pfx='http://example.org/' baz='2'>\n"
11908         "&en;"
11909         "</pfx:element>";
11910     ExtOption options[] = {
11911         { XCS("foo"), "<!ELEMENT e EMPTY>" },
11912         { XCS("bar"), "<e/>" },
11913         { NULL, NULL }
11914     };
11915     int i;
11916     const int max_alloc_count = 70;
11917 
11918     for (i = 0; i < max_alloc_count; i++) {
11919         allocation_count = i;
11920         XML_SetUserData(parser, options);
11921         XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11922         XML_SetExternalEntityRefHandler(parser, external_entity_optioner);
11923         if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text),
11924                                     XML_TRUE) != XML_STATUS_ERROR)
11925             break;
11926 
11927         /* See comment in test_nsalloc_xmlns() */
11928         nsalloc_teardown();
11929         nsalloc_setup();
11930     }
11931     if (i == 0)
11932         fail("Success despite failing allocator");
11933     else if (i == max_alloc_count)
11934         fail("Failed even at full allocation count");
11935 }
11936 END_TEST
11937 
11938 static Suite *
make_suite(void)11939 make_suite(void)
11940 {
11941     Suite *s = suite_create("basic");
11942     TCase *tc_basic = tcase_create("basic tests");
11943     TCase *tc_namespace = tcase_create("XML namespaces");
11944     TCase *tc_misc = tcase_create("miscellaneous tests");
11945     TCase *tc_alloc = tcase_create("allocation tests");
11946     TCase *tc_nsalloc = tcase_create("namespace allocation tests");
11947 
11948     suite_add_tcase(s, tc_basic);
11949     tcase_add_checked_fixture(tc_basic, basic_setup, basic_teardown);
11950     tcase_add_test(tc_basic, test_nul_byte);
11951     tcase_add_test(tc_basic, test_u0000_char);
11952     tcase_add_test(tc_basic, test_siphash_self);
11953     tcase_add_test(tc_basic, test_siphash_spec);
11954     tcase_add_test(tc_basic, test_bom_utf8);
11955     tcase_add_test(tc_basic, test_bom_utf16_be);
11956     tcase_add_test(tc_basic, test_bom_utf16_le);
11957     tcase_add_test(tc_basic, test_nobom_utf16_le);
11958     tcase_add_test(tc_basic, test_illegal_utf8);
11959     tcase_add_test(tc_basic, test_utf8_auto_align);
11960     tcase_add_test(tc_basic, test_utf16);
11961     tcase_add_test(tc_basic, test_utf16_le_epilog_newline);
11962     tcase_add_test(tc_basic, test_not_utf16);
11963     tcase_add_test(tc_basic, test_bad_encoding);
11964     tcase_add_test(tc_basic, test_latin1_umlauts);
11965     tcase_add_test(tc_basic, test_long_utf8_character);
11966     tcase_add_test(tc_basic, test_long_latin1_attribute);
11967     tcase_add_test(tc_basic, test_long_ascii_attribute);
11968     /* Regression test for SF bug #491986. */
11969     tcase_add_test(tc_basic, test_danish_latin1);
11970     /* Regression test for SF bug #514281. */
11971     tcase_add_test(tc_basic, test_french_charref_hexidecimal);
11972     tcase_add_test(tc_basic, test_french_charref_decimal);
11973     tcase_add_test(tc_basic, test_french_latin1);
11974     tcase_add_test(tc_basic, test_french_utf8);
11975     tcase_add_test(tc_basic, test_utf8_false_rejection);
11976     tcase_add_test(tc_basic, test_line_number_after_parse);
11977     tcase_add_test(tc_basic, test_column_number_after_parse);
11978     tcase_add_test(tc_basic, test_line_and_column_numbers_inside_handlers);
11979     tcase_add_test(tc_basic, test_line_number_after_error);
11980     tcase_add_test(tc_basic, test_column_number_after_error);
11981     tcase_add_test(tc_basic, test_really_long_lines);
11982     tcase_add_test(tc_basic, test_really_long_encoded_lines);
11983     tcase_add_test(tc_basic, test_end_element_events);
11984     tcase_add_test(tc_basic, test_attr_whitespace_normalization);
11985     tcase_add_test(tc_basic, test_xmldecl_misplaced);
11986     tcase_add_test(tc_basic, test_xmldecl_invalid);
11987     tcase_add_test(tc_basic, test_xmldecl_missing_attr);
11988     tcase_add_test(tc_basic, test_xmldecl_missing_value);
11989     tcase_add_test(tc_basic, test_unknown_encoding_internal_entity);
11990     tcase_add_test(tc_basic, test_unrecognised_encoding_internal_entity);
11991     tcase_add_test(tc_basic,
11992                    test_wfc_undeclared_entity_unread_external_subset);
11993     tcase_add_test(tc_basic, test_wfc_undeclared_entity_no_external_subset);
11994     tcase_add_test(tc_basic, test_wfc_undeclared_entity_standalone);
11995     tcase_add_test(tc_basic, test_wfc_undeclared_entity_with_external_subset);
11996     tcase_add_test(tc_basic, test_not_standalone_handler_reject);
11997     tcase_add_test(tc_basic, test_not_standalone_handler_accept);
11998     tcase_add_test(tc_basic,
11999                    test_wfc_undeclared_entity_with_external_subset_standalone);
12000     tcase_add_test(tc_basic,
12001                    test_entity_with_external_subset_unless_standalone);
12002     tcase_add_test(tc_basic, test_wfc_no_recursive_entity_refs);
12003     tcase_add_test(tc_basic, test_ext_entity_set_encoding);
12004     tcase_add_test(tc_basic, test_ext_entity_no_handler);
12005     tcase_add_test(tc_basic, test_ext_entity_set_bom);
12006     tcase_add_test(tc_basic, test_ext_entity_bad_encoding);
12007     tcase_add_test(tc_basic, test_ext_entity_bad_encoding_2);
12008     tcase_add_test(tc_basic, test_ext_entity_invalid_parse);
12009     tcase_add_test(tc_basic, test_ext_entity_invalid_suspended_parse);
12010     tcase_add_test(tc_basic, test_dtd_default_handling);
12011     tcase_add_test(tc_basic, test_dtd_attr_handling);
12012     tcase_add_test(tc_basic, test_empty_ns_without_namespaces);
12013     tcase_add_test(tc_basic, test_ns_in_attribute_default_without_namespaces);
12014     tcase_add_test(tc_basic, test_stop_parser_between_char_data_calls);
12015     tcase_add_test(tc_basic, test_suspend_parser_between_char_data_calls);
12016     tcase_add_test(tc_basic, test_repeated_stop_parser_between_char_data_calls);
12017     tcase_add_test(tc_basic, test_good_cdata_ascii);
12018     tcase_add_test(tc_basic, test_good_cdata_utf16);
12019     tcase_add_test(tc_basic, test_good_cdata_utf16_le);
12020     tcase_add_test(tc_basic, test_long_cdata_utf16);
12021     tcase_add_test(tc_basic, test_multichar_cdata_utf16);
12022     tcase_add_test(tc_basic, test_utf16_bad_surrogate_pair);
12023     tcase_add_test(tc_basic, test_bad_cdata);
12024     tcase_add_test(tc_basic, test_bad_cdata_utf16);
12025     tcase_add_test(tc_basic, test_stop_parser_between_cdata_calls);
12026     tcase_add_test(tc_basic, test_suspend_parser_between_cdata_calls);
12027     tcase_add_test(tc_basic, test_memory_allocation);
12028     tcase_add_test(tc_basic, test_default_current);
12029     tcase_add_test(tc_basic, test_dtd_elements);
12030     tcase_add_test(tc_basic, test_set_foreign_dtd);
12031     tcase_add_test(tc_basic, test_foreign_dtd_not_standalone);
12032     tcase_add_test(tc_basic, test_invalid_foreign_dtd);
12033     tcase_add_test(tc_basic, test_foreign_dtd_with_doctype);
12034     tcase_add_test(tc_basic, test_foreign_dtd_without_external_subset);
12035     tcase_add_test(tc_basic, test_empty_foreign_dtd);
12036     tcase_add_test(tc_basic, test_set_base);
12037     tcase_add_test(tc_basic, test_attributes);
12038     tcase_add_test(tc_basic, test_reset_in_entity);
12039     tcase_add_test(tc_basic, test_resume_invalid_parse);
12040     tcase_add_test(tc_basic, test_resume_resuspended);
12041     tcase_add_test(tc_basic, test_cdata_default);
12042     tcase_add_test(tc_basic, test_subordinate_reset);
12043     tcase_add_test(tc_basic, test_subordinate_suspend);
12044     tcase_add_test(tc_basic, test_subordinate_xdecl_suspend);
12045     tcase_add_test(tc_basic, test_subordinate_xdecl_abort);
12046     tcase_add_test(tc_basic, test_explicit_encoding);
12047     tcase_add_test(tc_basic, test_trailing_cr);
12048     tcase_add_test(tc_basic, test_ext_entity_trailing_cr);
12049     tcase_add_test(tc_basic, test_trailing_rsqb);
12050     tcase_add_test(tc_basic, test_ext_entity_trailing_rsqb);
12051     tcase_add_test(tc_basic, test_ext_entity_good_cdata);
12052     tcase_add_test(tc_basic, test_user_parameters);
12053     tcase_add_test(tc_basic, test_ext_entity_ref_parameter);
12054     tcase_add_test(tc_basic, test_empty_parse);
12055     tcase_add_test(tc_basic, test_get_buffer_1);
12056     tcase_add_test(tc_basic, test_get_buffer_2);
12057     tcase_add_test(tc_basic, test_byte_info_at_end);
12058     tcase_add_test(tc_basic, test_byte_info_at_error);
12059     tcase_add_test(tc_basic, test_byte_info_at_cdata);
12060     tcase_add_test(tc_basic, test_predefined_entities);
12061     tcase_add_test(tc_basic, test_invalid_tag_in_dtd);
12062     tcase_add_test(tc_basic, test_not_predefined_entities);
12063     tcase_add_test(tc_basic, test_ignore_section);
12064     tcase_add_test(tc_basic, test_ignore_section_utf16);
12065     tcase_add_test(tc_basic, test_ignore_section_utf16_be);
12066     tcase_add_test(tc_basic, test_bad_ignore_section);
12067     tcase_add_test(tc_basic, test_external_entity_values);
12068     tcase_add_test(tc_basic, test_ext_entity_not_standalone);
12069     tcase_add_test(tc_basic, test_ext_entity_value_abort);
12070     tcase_add_test(tc_basic, test_bad_public_doctype);
12071     tcase_add_test(tc_basic, test_attribute_enum_value);
12072     tcase_add_test(tc_basic, test_predefined_entity_redefinition);
12073     tcase_add_test(tc_basic, test_dtd_stop_processing);
12074     tcase_add_test(tc_basic, test_public_notation_no_sysid);
12075     tcase_add_test(tc_basic, test_nested_groups);
12076     tcase_add_test(tc_basic, test_group_choice);
12077     tcase_add_test(tc_basic, test_standalone_parameter_entity);
12078     tcase_add_test(tc_basic, test_skipped_parameter_entity);
12079     tcase_add_test(tc_basic, test_recursive_external_parameter_entity);
12080     tcase_add_test(tc_basic, test_undefined_ext_entity_in_external_dtd);
12081     tcase_add_test(tc_basic, test_suspend_xdecl);
12082     tcase_add_test(tc_basic, test_abort_epilog);
12083     tcase_add_test(tc_basic, test_abort_epilog_2);
12084     tcase_add_test(tc_basic, test_suspend_epilog);
12085     tcase_add_test(tc_basic, test_unfinished_epilog);
12086     tcase_add_test(tc_basic, test_partial_char_in_epilog);
12087     tcase_add_test(tc_basic, test_hash_collision);
12088     tcase_add_test(tc_basic, test_suspend_resume_internal_entity);
12089     tcase_add_test(tc_basic, test_resume_entity_with_syntax_error);
12090     tcase_add_test(tc_basic, test_suspend_resume_parameter_entity);
12091     tcase_add_test(tc_basic, test_restart_on_error);
12092     tcase_add_test(tc_basic, test_reject_lt_in_attribute_value);
12093     tcase_add_test(tc_basic, test_reject_unfinished_param_in_att_value);
12094     tcase_add_test(tc_basic, test_trailing_cr_in_att_value);
12095     tcase_add_test(tc_basic, test_standalone_internal_entity);
12096     tcase_add_test(tc_basic, test_skipped_external_entity);
12097     tcase_add_test(tc_basic, test_skipped_null_loaded_ext_entity);
12098     tcase_add_test(tc_basic, test_skipped_unloaded_ext_entity);
12099     tcase_add_test(tc_basic, test_param_entity_with_trailing_cr);
12100     tcase_add_test(tc_basic, test_invalid_character_entity);
12101     tcase_add_test(tc_basic, test_invalid_character_entity_2);
12102     tcase_add_test(tc_basic, test_invalid_character_entity_3);
12103     tcase_add_test(tc_basic, test_invalid_character_entity_4);
12104     tcase_add_test(tc_basic, test_pi_handled_in_default);
12105     tcase_add_test(tc_basic, test_comment_handled_in_default);
12106     tcase_add_test(tc_basic, test_pi_yml);
12107     tcase_add_test(tc_basic, test_pi_xnl);
12108     tcase_add_test(tc_basic, test_pi_xmm);
12109     tcase_add_test(tc_basic, test_utf16_pi);
12110     tcase_add_test(tc_basic, test_utf16_be_pi);
12111     tcase_add_test(tc_basic, test_utf16_be_comment);
12112     tcase_add_test(tc_basic, test_utf16_le_comment);
12113     tcase_add_test(tc_basic, test_missing_encoding_conversion_fn);
12114     tcase_add_test(tc_basic, test_failing_encoding_conversion_fn);
12115     tcase_add_test(tc_basic, test_unknown_encoding_success);
12116     tcase_add_test(tc_basic, test_unknown_encoding_bad_name);
12117     tcase_add_test(tc_basic, test_unknown_encoding_bad_name_2);
12118     tcase_add_test(tc_basic, test_unknown_encoding_long_name_1);
12119     tcase_add_test(tc_basic, test_unknown_encoding_long_name_2);
12120     tcase_add_test(tc_basic, test_invalid_unknown_encoding);
12121     tcase_add_test(tc_basic, test_unknown_ascii_encoding_ok);
12122     tcase_add_test(tc_basic, test_unknown_ascii_encoding_fail);
12123     tcase_add_test(tc_basic, test_unknown_encoding_invalid_length);
12124     tcase_add_test(tc_basic, test_unknown_encoding_invalid_topbit);
12125     tcase_add_test(tc_basic, test_unknown_encoding_invalid_surrogate);
12126     tcase_add_test(tc_basic, test_unknown_encoding_invalid_high);
12127     tcase_add_test(tc_basic, test_unknown_encoding_invalid_attr_value);
12128     tcase_add_test(tc_basic, test_ext_entity_latin1_utf16le_bom);
12129     tcase_add_test(tc_basic, test_ext_entity_latin1_utf16be_bom);
12130     tcase_add_test(tc_basic, test_ext_entity_latin1_utf16le_bom2);
12131     tcase_add_test(tc_basic, test_ext_entity_latin1_utf16be_bom2);
12132     tcase_add_test(tc_basic, test_ext_entity_utf16_be);
12133     tcase_add_test(tc_basic, test_ext_entity_utf16_le);
12134     tcase_add_test(tc_basic, test_ext_entity_utf16_unknown);
12135     tcase_add_test(tc_basic, test_ext_entity_utf8_non_bom);
12136     tcase_add_test(tc_basic, test_utf8_in_cdata_section);
12137     tcase_add_test(tc_basic, test_utf8_in_cdata_section_2);
12138     tcase_add_test(tc_basic, test_trailing_spaces_in_elements);
12139     tcase_add_test(tc_basic, test_utf16_attribute);
12140     tcase_add_test(tc_basic, test_utf16_second_attr);
12141     tcase_add_test(tc_basic, test_attr_after_solidus);
12142     tcase_add_test(tc_basic, test_utf16_pe);
12143     tcase_add_test(tc_basic, test_bad_attr_desc_keyword);
12144     tcase_add_test(tc_basic, test_bad_attr_desc_keyword_utf16);
12145     tcase_add_test(tc_basic, test_bad_doctype);
12146     tcase_add_test(tc_basic, test_bad_doctype_utf16);
12147     tcase_add_test(tc_basic, test_bad_doctype_plus);
12148     tcase_add_test(tc_basic, test_bad_doctype_star);
12149     tcase_add_test(tc_basic, test_bad_doctype_query);
12150     tcase_add_test(tc_basic, test_unknown_encoding_bad_ignore);
12151     tcase_add_test(tc_basic, test_entity_in_utf16_be_attr);
12152     tcase_add_test(tc_basic, test_entity_in_utf16_le_attr);
12153     tcase_add_test(tc_basic, test_entity_public_utf16_be);
12154     tcase_add_test(tc_basic, test_entity_public_utf16_le);
12155     tcase_add_test(tc_basic, test_short_doctype);
12156     tcase_add_test(tc_basic, test_short_doctype_2);
12157     tcase_add_test(tc_basic, test_short_doctype_3);
12158     tcase_add_test(tc_basic, test_long_doctype);
12159     tcase_add_test(tc_basic, test_bad_entity);
12160     tcase_add_test(tc_basic, test_bad_entity_2);
12161     tcase_add_test(tc_basic, test_bad_entity_3);
12162     tcase_add_test(tc_basic, test_bad_entity_4);
12163     tcase_add_test(tc_basic, test_bad_notation);
12164     tcase_add_test(tc_basic, test_default_doctype_handler);
12165     tcase_add_test(tc_basic, test_empty_element_abort);
12166 
12167     suite_add_tcase(s, tc_namespace);
12168     tcase_add_checked_fixture(tc_namespace,
12169                               namespace_setup, namespace_teardown);
12170     tcase_add_test(tc_namespace, test_return_ns_triplet);
12171     tcase_add_test(tc_namespace, test_ns_tagname_overwrite);
12172     tcase_add_test(tc_namespace, test_ns_tagname_overwrite_triplet);
12173     tcase_add_test(tc_namespace, test_start_ns_clears_start_element);
12174     tcase_add_test(tc_namespace, test_default_ns_from_ext_subset_and_ext_ge);
12175     tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_1);
12176     tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_2);
12177     tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_3);
12178     tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_4);
12179     tcase_add_test(tc_namespace, test_ns_unbound_prefix);
12180     tcase_add_test(tc_namespace, test_ns_default_with_empty_uri);
12181     tcase_add_test(tc_namespace, test_ns_duplicate_attrs_diff_prefixes);
12182     tcase_add_test(tc_namespace, test_ns_duplicate_hashes);
12183     tcase_add_test(tc_namespace, test_ns_unbound_prefix_on_attribute);
12184     tcase_add_test(tc_namespace, test_ns_unbound_prefix_on_element);
12185     tcase_add_test(tc_namespace, test_ns_parser_reset);
12186     tcase_add_test(tc_namespace, test_ns_long_element);
12187     tcase_add_test(tc_namespace, test_ns_mixed_prefix_atts);
12188     tcase_add_test(tc_namespace, test_ns_extend_uri_buffer);
12189     tcase_add_test(tc_namespace, test_ns_reserved_attributes);
12190     tcase_add_test(tc_namespace, test_ns_reserved_attributes_2);
12191     tcase_add_test(tc_namespace, test_ns_extremely_long_prefix);
12192     tcase_add_test(tc_namespace, test_ns_unknown_encoding_success);
12193     tcase_add_test(tc_namespace, test_ns_double_colon);
12194     tcase_add_test(tc_namespace, test_ns_double_colon_element);
12195     tcase_add_test(tc_namespace, test_ns_bad_attr_leafname);
12196     tcase_add_test(tc_namespace, test_ns_bad_element_leafname);
12197     tcase_add_test(tc_namespace, test_ns_utf16_leafname);
12198     tcase_add_test(tc_namespace, test_ns_utf16_element_leafname);
12199     tcase_add_test(tc_namespace, test_ns_utf16_doctype);
12200     tcase_add_test(tc_namespace, test_ns_invalid_doctype);
12201     tcase_add_test(tc_namespace, test_ns_double_colon_doctype);
12202 
12203     suite_add_tcase(s, tc_misc);
12204     tcase_add_checked_fixture(tc_misc, NULL, basic_teardown);
12205     tcase_add_test(tc_misc, test_misc_alloc_create_parser);
12206     tcase_add_test(tc_misc, test_misc_alloc_create_parser_with_encoding);
12207     tcase_add_test(tc_misc, test_misc_null_parser);
12208     tcase_add_test(tc_misc, test_misc_error_string);
12209     tcase_add_test(tc_misc, test_misc_version);
12210     tcase_add_test(tc_misc, test_misc_features);
12211     tcase_add_test(tc_misc, test_misc_attribute_leak);
12212     tcase_add_test(tc_misc, test_misc_utf16le);
12213 
12214     suite_add_tcase(s, tc_alloc);
12215     tcase_add_checked_fixture(tc_alloc, alloc_setup, alloc_teardown);
12216     tcase_add_test(tc_alloc, test_alloc_parse_xdecl);
12217     tcase_add_test(tc_alloc, test_alloc_parse_xdecl_2);
12218     tcase_add_test(tc_alloc, test_alloc_parse_pi);
12219     tcase_add_test(tc_alloc, test_alloc_parse_pi_2);
12220     tcase_add_test(tc_alloc, test_alloc_parse_pi_3);
12221     tcase_add_test(tc_alloc, test_alloc_parse_comment);
12222     tcase_add_test(tc_alloc, test_alloc_parse_comment_2);
12223     tcase_add_test(tc_alloc, test_alloc_create_external_parser);
12224     tcase_add_test(tc_alloc, test_alloc_run_external_parser);
12225     tcase_add_test(tc_alloc, test_alloc_dtd_copy_default_atts);
12226     tcase_add_test(tc_alloc, test_alloc_external_entity);
12227     tcase_add_test(tc_alloc, test_alloc_ext_entity_set_encoding);
12228     tcase_add_test(tc_alloc, test_alloc_internal_entity);
12229     tcase_add_test(tc_alloc, test_alloc_dtd_default_handling);
12230     tcase_add_test(tc_alloc, test_alloc_explicit_encoding);
12231     tcase_add_test(tc_alloc, test_alloc_set_base);
12232     tcase_add_test(tc_alloc, test_alloc_realloc_buffer);
12233     tcase_add_test(tc_alloc, test_alloc_ext_entity_realloc_buffer);
12234     tcase_add_test(tc_alloc, test_alloc_realloc_many_attributes);
12235     tcase_add_test(tc_alloc, test_alloc_public_entity_value);
12236     tcase_add_test(tc_alloc, test_alloc_realloc_subst_public_entity_value);
12237     tcase_add_test(tc_alloc, test_alloc_parse_public_doctype);
12238     tcase_add_test(tc_alloc, test_alloc_parse_public_doctype_long_name);
12239     tcase_add_test(tc_alloc, test_alloc_set_foreign_dtd);
12240     tcase_add_test(tc_alloc, test_alloc_attribute_enum_value);
12241     tcase_add_test(tc_alloc, test_alloc_realloc_attribute_enum_value);
12242     tcase_add_test(tc_alloc, test_alloc_realloc_implied_attribute);
12243     tcase_add_test(tc_alloc, test_alloc_realloc_default_attribute);
12244     tcase_add_test(tc_alloc, test_alloc_notation);
12245     tcase_add_test(tc_alloc, test_alloc_public_notation);
12246     tcase_add_test(tc_alloc, test_alloc_system_notation);
12247     tcase_add_test(tc_alloc, test_alloc_nested_groups);
12248     tcase_add_test(tc_alloc, test_alloc_realloc_nested_groups);
12249     tcase_add_test(tc_alloc, test_alloc_large_group);
12250     tcase_add_test(tc_alloc, test_alloc_realloc_group_choice);
12251     tcase_add_test(tc_alloc, test_alloc_pi_in_epilog);
12252     tcase_add_test(tc_alloc, test_alloc_comment_in_epilog);
12253     tcase_add_test(tc_alloc, test_alloc_realloc_long_attribute_value);
12254     tcase_add_test(tc_alloc, test_alloc_attribute_whitespace);
12255     tcase_add_test(tc_alloc, test_alloc_attribute_predefined_entity);
12256     tcase_add_test(tc_alloc, test_alloc_long_attr_default_with_char_ref);
12257     tcase_add_test(tc_alloc, test_alloc_long_attr_value);
12258     tcase_add_test(tc_alloc, test_alloc_nested_entities);
12259     tcase_add_test(tc_alloc, test_alloc_realloc_param_entity_newline);
12260     tcase_add_test(tc_alloc, test_alloc_realloc_ce_extends_pe);
12261     tcase_add_test(tc_alloc, test_alloc_realloc_attributes);
12262     tcase_add_test(tc_alloc, test_alloc_long_doc_name);
12263     tcase_add_test(tc_alloc, test_alloc_long_base);
12264     tcase_add_test(tc_alloc, test_alloc_long_public_id);
12265     tcase_add_test(tc_alloc, test_alloc_long_entity_value);
12266     tcase_add_test(tc_alloc, test_alloc_long_notation);
12267 
12268     suite_add_tcase(s, tc_nsalloc);
12269     tcase_add_checked_fixture(tc_nsalloc, nsalloc_setup, nsalloc_teardown);
12270     tcase_add_test(tc_nsalloc, test_nsalloc_xmlns);
12271     tcase_add_test(tc_nsalloc, test_nsalloc_parse_buffer);
12272     tcase_add_test(tc_nsalloc, test_nsalloc_long_prefix);
12273     tcase_add_test(tc_nsalloc, test_nsalloc_long_uri);
12274     tcase_add_test(tc_nsalloc, test_nsalloc_long_attr);
12275     tcase_add_test(tc_nsalloc, test_nsalloc_long_attr_prefix);
12276     tcase_add_test(tc_nsalloc, test_nsalloc_realloc_attributes);
12277     tcase_add_test(tc_nsalloc, test_nsalloc_long_element);
12278     tcase_add_test(tc_nsalloc, test_nsalloc_realloc_binding_uri);
12279     tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_prefix);
12280     tcase_add_test(tc_nsalloc, test_nsalloc_realloc_longer_prefix);
12281     tcase_add_test(tc_nsalloc, test_nsalloc_long_namespace);
12282     tcase_add_test(tc_nsalloc, test_nsalloc_less_long_namespace);
12283     tcase_add_test(tc_nsalloc, test_nsalloc_long_context);
12284     tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context);
12285     tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_2);
12286     tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_3);
12287     tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_4);
12288     tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_5);
12289     tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_6);
12290     tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_7);
12291     tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_ge_name);
12292     tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_in_dtd);
12293     tcase_add_test(tc_nsalloc, test_nsalloc_long_default_in_ext);
12294     tcase_add_test(tc_nsalloc, test_nsalloc_long_systemid_in_ext);
12295     tcase_add_test(tc_nsalloc, test_nsalloc_prefixed_element);
12296 
12297     return s;
12298 }
12299 
12300 
12301 int
main(int argc,char * argv[])12302 main(int argc, char *argv[])
12303 {
12304     int i, nf;
12305     int verbosity = CK_NORMAL;
12306     Suite *s = make_suite();
12307     SRunner *sr = srunner_create(s);
12308 
12309     /* run the tests for internal helper functions */
12310     testhelper_is_whitespace_normalized();
12311 
12312     for (i = 1; i < argc; ++i) {
12313         char *opt = argv[i];
12314         if (strcmp(opt, "-v") == 0 || strcmp(opt, "--verbose") == 0)
12315             verbosity = CK_VERBOSE;
12316         else if (strcmp(opt, "-q") == 0 || strcmp(opt, "--quiet") == 0)
12317             verbosity = CK_SILENT;
12318         else {
12319             fprintf(stderr, "runtests: unknown option '%s'\n", opt);
12320             return 2;
12321         }
12322     }
12323     if (verbosity != CK_SILENT)
12324         printf("Expat version: %" XML_FMT_STR "\n", XML_ExpatVersion());
12325     srunner_run_all(sr, verbosity);
12326     nf = srunner_ntests_failed(sr);
12327     srunner_free(sr);
12328 
12329     return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
12330 }
12331