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>�</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>éèàçêÈ</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>éèàçêÈ</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 ä ö ü ä ö ü >'\n"
923 " >\xE4 \xF6 \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 '&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 '%'>\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><>&"'</doc>";
4223 const XML_Char *expected = XCS("<doc><>&"'</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>'</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 '%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 \"≥\">'>\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 '�'>\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 '�'>\n" /* = � */
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='ä ä'></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='ä ä'></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='&'></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 "1'>]>\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 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGQ"
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