1 /* Run the Expat test suite
2 __ __ _
3 ___\ \/ /_ __ __ _| |_
4 / _ \\ /| '_ \ / _` | __|
5 | __// \| |_) | (_| | |_
6 \___/_/\_\ .__/ \__,_|\__|
7 |_| XML parser
8
9 Copyright (c) 2001-2006 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
10 Copyright (c) 2003 Greg Stein <gstein@users.sourceforge.net>
11 Copyright (c) 2005-2007 Steven Solie <ssolie@users.sourceforge.net>
12 Copyright (c) 2005-2012 Karl Waclawek <karl@waclawek.net>
13 Copyright (c) 2016-2021 Sebastian Pipping <sebastian@pipping.org>
14 Copyright (c) 2017-2018 Rhodri James <rhodri@wildebeest.org.uk>
15 Copyright (c) 2017 Joe Orton <jorton@redhat.com>
16 Copyright (c) 2017 José Gutiérrez de la Concha <jose@zeroc.com>
17 Copyright (c) 2018 Marco Maggi <marco.maggi-ipsu@poste.it>
18 Copyright (c) 2019 David Loffredo <loffredo@steptools.com>
19 Copyright (c) 2020 Tim Gates <tim.gates@iress.com>
20 Licensed under the MIT license:
21
22 Permission is hereby granted, free of charge, to any person obtaining
23 a copy of this software and associated documentation files (the
24 "Software"), to deal in the Software without restriction, including
25 without limitation the rights to use, copy, modify, merge, publish,
26 distribute, sublicense, and/or sell copies of the Software, and to permit
27 persons to whom the Software is furnished to do so, subject to the
28 following conditions:
29
30 The above copyright notice and this permission notice shall be included
31 in all copies or substantial portions of the Software.
32
33 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
34 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
35 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
36 NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
37 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
38 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
39 USE OR OTHER DEALINGS IN THE SOFTWARE.
40 */
41
42 #if defined(NDEBUG)
43 # undef NDEBUG /* because test suite relies on assert(...) at the moment */
44 #endif
45
46 #include <expat_config.h>
47
48 #include <assert.h>
49 #include <stdlib.h>
50 #include <stdio.h>
51 #include <string.h>
52 #include <stddef.h> /* ptrdiff_t */
53 #include <ctype.h>
54 #include <limits.h>
55 #include <stdint.h> /* intptr_t uint64_t */
56 #include <math.h> /* NAN, INFINITY, isnan */
57
58 #if ! defined(__cplusplus)
59 # include <stdbool.h>
60 #endif
61
62 #include "expat.h"
63 #include "chardata.h"
64 #include "structdata.h"
65 #include "internal.h"
66 #include "minicheck.h"
67 #include "memcheck.h"
68 #include "siphash.h"
69 #include "ascii.h" /* for ASCII_xxx */
70
71 #ifdef XML_LARGE_SIZE
72 # define XML_FMT_INT_MOD "ll"
73 #else
74 # define XML_FMT_INT_MOD "l"
75 #endif
76
77 #ifdef XML_UNICODE_WCHAR_T
78 # define XML_FMT_CHAR "lc"
79 # define XML_FMT_STR "ls"
80 # include <wchar.h>
81 # define xcstrlen(s) wcslen(s)
82 # define xcstrcmp(s, t) wcscmp((s), (t))
83 # define xcstrncmp(s, t, n) wcsncmp((s), (t), (n))
84 # define XCS(s) _XCS(s)
85 # define _XCS(s) L##s
86 #else
87 # ifdef XML_UNICODE
88 # error "No support for UTF-16 character without wchar_t in tests"
89 # else
90 # define XML_FMT_CHAR "c"
91 # define XML_FMT_STR "s"
92 # define xcstrlen(s) strlen(s)
93 # define xcstrcmp(s, t) strcmp((s), (t))
94 # define xcstrncmp(s, t, n) strncmp((s), (t), (n))
95 # define XCS(s) s
96 # endif /* XML_UNICODE */
97 #endif /* XML_UNICODE_WCHAR_T */
98
99 static XML_Parser g_parser = NULL;
100
101 static void
tcase_add_test__ifdef_xml_dtd(TCase * tc,tcase_test_function test)102 tcase_add_test__ifdef_xml_dtd(TCase *tc, tcase_test_function test) {
103 #ifdef XML_DTD
104 tcase_add_test(tc, test);
105 #else
106 UNUSED_P(tc);
107 UNUSED_P(test);
108 #endif
109 }
110
111 static void
basic_setup(void)112 basic_setup(void) {
113 g_parser = XML_ParserCreate(NULL);
114 if (g_parser == NULL)
115 fail("Parser not created.");
116 }
117
118 static void
basic_teardown(void)119 basic_teardown(void) {
120 if (g_parser != NULL) {
121 XML_ParserFree(g_parser);
122 g_parser = NULL;
123 }
124 }
125
126 /* Generate a failure using the parser state to create an error message;
127 this should be used when the parser reports an error we weren't
128 expecting.
129 */
130 static void
_xml_failure(XML_Parser parser,const char * file,int line)131 _xml_failure(XML_Parser parser, const char *file, int line) {
132 char buffer[1024];
133 enum XML_Error err = XML_GetErrorCode(parser);
134 sprintf(buffer,
135 " %d: %" XML_FMT_STR " (line %" XML_FMT_INT_MOD
136 "u, offset %" XML_FMT_INT_MOD "u)\n reported from %s, line %d\n",
137 err, XML_ErrorString(err), XML_GetCurrentLineNumber(parser),
138 XML_GetCurrentColumnNumber(parser), file, line);
139 _fail_unless(0, file, line, buffer);
140 }
141
142 static enum XML_Status
_XML_Parse_SINGLE_BYTES(XML_Parser parser,const char * s,int len,int isFinal)143 _XML_Parse_SINGLE_BYTES(XML_Parser parser, const char *s, int len,
144 int isFinal) {
145 enum XML_Status res = XML_STATUS_ERROR;
146 int offset = 0;
147
148 if (len == 0) {
149 return XML_Parse(parser, s, len, isFinal);
150 }
151
152 for (; offset < len; offset++) {
153 const int innerIsFinal = (offset == len - 1) && isFinal;
154 const char c = s[offset]; /* to help out-of-bounds detection */
155 res = XML_Parse(parser, &c, sizeof(char), innerIsFinal);
156 if (res != XML_STATUS_OK) {
157 return res;
158 }
159 }
160 return res;
161 }
162
163 #define xml_failure(parser) _xml_failure((parser), __FILE__, __LINE__)
164
165 static void
_expect_failure(const char * text,enum XML_Error errorCode,const char * errorMessage,const char * file,int lineno)166 _expect_failure(const char *text, enum XML_Error errorCode,
167 const char *errorMessage, const char *file, int lineno) {
168 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
169 == XML_STATUS_OK)
170 /* Hackish use of _fail_unless() macro, but let's us report
171 the right filename and line number. */
172 _fail_unless(0, file, lineno, errorMessage);
173 if (XML_GetErrorCode(g_parser) != errorCode)
174 _xml_failure(g_parser, file, lineno);
175 }
176
177 #define expect_failure(text, errorCode, errorMessage) \
178 _expect_failure((text), (errorCode), (errorMessage), __FILE__, __LINE__)
179
180 /* Dummy handlers for when we need to set a handler to tickle a bug,
181 but it doesn't need to do anything.
182 */
183 static unsigned long dummy_handler_flags = 0;
184
185 #define DUMMY_START_DOCTYPE_HANDLER_FLAG (1UL << 0)
186 #define DUMMY_END_DOCTYPE_HANDLER_FLAG (1UL << 1)
187 #define DUMMY_ENTITY_DECL_HANDLER_FLAG (1UL << 2)
188 #define DUMMY_NOTATION_DECL_HANDLER_FLAG (1UL << 3)
189 #define DUMMY_ELEMENT_DECL_HANDLER_FLAG (1UL << 4)
190 #define DUMMY_ATTLIST_DECL_HANDLER_FLAG (1UL << 5)
191 #define DUMMY_COMMENT_HANDLER_FLAG (1UL << 6)
192 #define DUMMY_PI_HANDLER_FLAG (1UL << 7)
193 #define DUMMY_START_ELEMENT_HANDLER_FLAG (1UL << 8)
194 #define DUMMY_START_CDATA_HANDLER_FLAG (1UL << 9)
195 #define DUMMY_END_CDATA_HANDLER_FLAG (1UL << 10)
196 #define DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG (1UL << 11)
197 #define DUMMY_START_NS_DECL_HANDLER_FLAG (1UL << 12)
198 #define DUMMY_END_NS_DECL_HANDLER_FLAG (1UL << 13)
199 #define DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG (1UL << 14)
200 #define DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG (1UL << 15)
201 #define DUMMY_SKIP_HANDLER_FLAG (1UL << 16)
202 #define DUMMY_DEFAULT_HANDLER_FLAG (1UL << 17)
203
204 static void XMLCALL
dummy_xdecl_handler(void * userData,const XML_Char * version,const XML_Char * encoding,int standalone)205 dummy_xdecl_handler(void *userData, const XML_Char *version,
206 const XML_Char *encoding, int standalone) {
207 UNUSED_P(userData);
208 UNUSED_P(version);
209 UNUSED_P(encoding);
210 UNUSED_P(standalone);
211 }
212
213 static void XMLCALL
dummy_start_doctype_handler(void * userData,const XML_Char * doctypeName,const XML_Char * sysid,const XML_Char * pubid,int has_internal_subset)214 dummy_start_doctype_handler(void *userData, const XML_Char *doctypeName,
215 const XML_Char *sysid, const XML_Char *pubid,
216 int has_internal_subset) {
217 UNUSED_P(userData);
218 UNUSED_P(doctypeName);
219 UNUSED_P(sysid);
220 UNUSED_P(pubid);
221 UNUSED_P(has_internal_subset);
222 dummy_handler_flags |= DUMMY_START_DOCTYPE_HANDLER_FLAG;
223 }
224
225 static void XMLCALL
dummy_end_doctype_handler(void * userData)226 dummy_end_doctype_handler(void *userData) {
227 UNUSED_P(userData);
228 dummy_handler_flags |= DUMMY_END_DOCTYPE_HANDLER_FLAG;
229 }
230
231 static void XMLCALL
dummy_entity_decl_handler(void * userData,const XML_Char * entityName,int is_parameter_entity,const XML_Char * value,int value_length,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId,const XML_Char * notationName)232 dummy_entity_decl_handler(void *userData, const XML_Char *entityName,
233 int is_parameter_entity, const XML_Char *value,
234 int value_length, const XML_Char *base,
235 const XML_Char *systemId, const XML_Char *publicId,
236 const XML_Char *notationName) {
237 UNUSED_P(userData);
238 UNUSED_P(entityName);
239 UNUSED_P(is_parameter_entity);
240 UNUSED_P(value);
241 UNUSED_P(value_length);
242 UNUSED_P(base);
243 UNUSED_P(systemId);
244 UNUSED_P(publicId);
245 UNUSED_P(notationName);
246 dummy_handler_flags |= DUMMY_ENTITY_DECL_HANDLER_FLAG;
247 }
248
249 static void XMLCALL
dummy_notation_decl_handler(void * userData,const XML_Char * notationName,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)250 dummy_notation_decl_handler(void *userData, const XML_Char *notationName,
251 const XML_Char *base, const XML_Char *systemId,
252 const XML_Char *publicId) {
253 UNUSED_P(userData);
254 UNUSED_P(notationName);
255 UNUSED_P(base);
256 UNUSED_P(systemId);
257 UNUSED_P(publicId);
258 dummy_handler_flags |= DUMMY_NOTATION_DECL_HANDLER_FLAG;
259 }
260
261 static void XMLCALL
dummy_element_decl_handler(void * userData,const XML_Char * name,XML_Content * model)262 dummy_element_decl_handler(void *userData, const XML_Char *name,
263 XML_Content *model) {
264 UNUSED_P(userData);
265 UNUSED_P(name);
266 /* The content model must be freed by the handler. Unfortunately
267 * we cannot pass the parser as the userData because this is used
268 * with other handlers that require other userData.
269 */
270 XML_FreeContentModel(g_parser, model);
271 dummy_handler_flags |= DUMMY_ELEMENT_DECL_HANDLER_FLAG;
272 }
273
274 static void XMLCALL
dummy_attlist_decl_handler(void * userData,const XML_Char * elname,const XML_Char * attname,const XML_Char * att_type,const XML_Char * dflt,int isrequired)275 dummy_attlist_decl_handler(void *userData, const XML_Char *elname,
276 const XML_Char *attname, const XML_Char *att_type,
277 const XML_Char *dflt, int isrequired) {
278 UNUSED_P(userData);
279 UNUSED_P(elname);
280 UNUSED_P(attname);
281 UNUSED_P(att_type);
282 UNUSED_P(dflt);
283 UNUSED_P(isrequired);
284 dummy_handler_flags |= DUMMY_ATTLIST_DECL_HANDLER_FLAG;
285 }
286
287 static void XMLCALL
dummy_comment_handler(void * userData,const XML_Char * data)288 dummy_comment_handler(void *userData, const XML_Char *data) {
289 UNUSED_P(userData);
290 UNUSED_P(data);
291 dummy_handler_flags |= DUMMY_COMMENT_HANDLER_FLAG;
292 }
293
294 static void XMLCALL
dummy_pi_handler(void * userData,const XML_Char * target,const XML_Char * data)295 dummy_pi_handler(void *userData, const XML_Char *target, const XML_Char *data) {
296 UNUSED_P(userData);
297 UNUSED_P(target);
298 UNUSED_P(data);
299 dummy_handler_flags |= DUMMY_PI_HANDLER_FLAG;
300 }
301
302 static void XMLCALL
dummy_start_element(void * userData,const XML_Char * name,const XML_Char ** atts)303 dummy_start_element(void *userData, const XML_Char *name,
304 const XML_Char **atts) {
305 UNUSED_P(userData);
306 UNUSED_P(name);
307 UNUSED_P(atts);
308 dummy_handler_flags |= DUMMY_START_ELEMENT_HANDLER_FLAG;
309 }
310
311 static void XMLCALL
dummy_end_element(void * userData,const XML_Char * name)312 dummy_end_element(void *userData, const XML_Char *name) {
313 UNUSED_P(userData);
314 UNUSED_P(name);
315 }
316
317 static void XMLCALL
dummy_start_cdata_handler(void * userData)318 dummy_start_cdata_handler(void *userData) {
319 UNUSED_P(userData);
320 dummy_handler_flags |= DUMMY_START_CDATA_HANDLER_FLAG;
321 }
322
323 static void XMLCALL
dummy_end_cdata_handler(void * userData)324 dummy_end_cdata_handler(void *userData) {
325 UNUSED_P(userData);
326 dummy_handler_flags |= DUMMY_END_CDATA_HANDLER_FLAG;
327 }
328
329 static void XMLCALL
dummy_cdata_handler(void * userData,const XML_Char * s,int len)330 dummy_cdata_handler(void *userData, const XML_Char *s, int len) {
331 UNUSED_P(userData);
332 UNUSED_P(s);
333 UNUSED_P(len);
334 }
335
336 static void XMLCALL
dummy_start_namespace_decl_handler(void * userData,const XML_Char * prefix,const XML_Char * uri)337 dummy_start_namespace_decl_handler(void *userData, const XML_Char *prefix,
338 const XML_Char *uri) {
339 UNUSED_P(userData);
340 UNUSED_P(prefix);
341 UNUSED_P(uri);
342 dummy_handler_flags |= DUMMY_START_NS_DECL_HANDLER_FLAG;
343 }
344
345 static void XMLCALL
dummy_end_namespace_decl_handler(void * userData,const XML_Char * prefix)346 dummy_end_namespace_decl_handler(void *userData, const XML_Char *prefix) {
347 UNUSED_P(userData);
348 UNUSED_P(prefix);
349 dummy_handler_flags |= DUMMY_END_NS_DECL_HANDLER_FLAG;
350 }
351
352 /* This handler is obsolete, but while the code exists we should
353 * ensure that dealing with the handler is covered by tests.
354 */
355 static void XMLCALL
dummy_unparsed_entity_decl_handler(void * userData,const XML_Char * entityName,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId,const XML_Char * notationName)356 dummy_unparsed_entity_decl_handler(void *userData, const XML_Char *entityName,
357 const XML_Char *base,
358 const XML_Char *systemId,
359 const XML_Char *publicId,
360 const XML_Char *notationName) {
361 UNUSED_P(userData);
362 UNUSED_P(entityName);
363 UNUSED_P(base);
364 UNUSED_P(systemId);
365 UNUSED_P(publicId);
366 UNUSED_P(notationName);
367 dummy_handler_flags |= DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG;
368 }
369
370 static void XMLCALL
dummy_default_handler(void * userData,const XML_Char * s,int len)371 dummy_default_handler(void *userData, const XML_Char *s, int len) {
372 UNUSED_P(userData);
373 UNUSED_P(s);
374 UNUSED_P(len);
375 }
376
377 static void XMLCALL
dummy_start_doctype_decl_handler(void * userData,const XML_Char * doctypeName,const XML_Char * sysid,const XML_Char * pubid,int has_internal_subset)378 dummy_start_doctype_decl_handler(void *userData, const XML_Char *doctypeName,
379 const XML_Char *sysid, const XML_Char *pubid,
380 int has_internal_subset) {
381 UNUSED_P(userData);
382 UNUSED_P(doctypeName);
383 UNUSED_P(sysid);
384 UNUSED_P(pubid);
385 UNUSED_P(has_internal_subset);
386 dummy_handler_flags |= DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG;
387 }
388
389 static void XMLCALL
dummy_end_doctype_decl_handler(void * userData)390 dummy_end_doctype_decl_handler(void *userData) {
391 UNUSED_P(userData);
392 dummy_handler_flags |= DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG;
393 }
394
395 static void XMLCALL
dummy_skip_handler(void * userData,const XML_Char * entityName,int is_parameter_entity)396 dummy_skip_handler(void *userData, const XML_Char *entityName,
397 int is_parameter_entity) {
398 UNUSED_P(userData);
399 UNUSED_P(entityName);
400 UNUSED_P(is_parameter_entity);
401 dummy_handler_flags |= DUMMY_SKIP_HANDLER_FLAG;
402 }
403
404 /* Useful external entity handler */
405 typedef struct ExtOption {
406 const XML_Char *system_id;
407 const char *parse_text;
408 } ExtOption;
409
410 static int XMLCALL
external_entity_optioner(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)411 external_entity_optioner(XML_Parser parser, const XML_Char *context,
412 const XML_Char *base, const XML_Char *systemId,
413 const XML_Char *publicId) {
414 ExtOption *options = (ExtOption *)XML_GetUserData(parser);
415 XML_Parser ext_parser;
416
417 UNUSED_P(base);
418 UNUSED_P(publicId);
419 while (options->parse_text != NULL) {
420 if (! xcstrcmp(systemId, options->system_id)) {
421 enum XML_Status rc;
422 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
423 if (ext_parser == NULL)
424 return XML_STATUS_ERROR;
425 rc = _XML_Parse_SINGLE_BYTES(ext_parser, options->parse_text,
426 (int)strlen(options->parse_text), XML_TRUE);
427 XML_ParserFree(ext_parser);
428 return rc;
429 }
430 options++;
431 }
432 fail("No suitable option found");
433 return XML_STATUS_ERROR;
434 }
435
436 /*
437 * Parameter entity evaluation support.
438 */
439 #define ENTITY_MATCH_FAIL (-1)
440 #define ENTITY_MATCH_NOT_FOUND (0)
441 #define ENTITY_MATCH_SUCCESS (1)
442 static const XML_Char *entity_name_to_match = NULL;
443 static const XML_Char *entity_value_to_match = NULL;
444 static int entity_match_flag = ENTITY_MATCH_NOT_FOUND;
445
446 static void XMLCALL
param_entity_match_handler(void * userData,const XML_Char * entityName,int is_parameter_entity,const XML_Char * value,int value_length,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId,const XML_Char * notationName)447 param_entity_match_handler(void *userData, const XML_Char *entityName,
448 int is_parameter_entity, const XML_Char *value,
449 int value_length, const XML_Char *base,
450 const XML_Char *systemId, const XML_Char *publicId,
451 const XML_Char *notationName) {
452 UNUSED_P(userData);
453 UNUSED_P(base);
454 UNUSED_P(systemId);
455 UNUSED_P(publicId);
456 UNUSED_P(notationName);
457 if (! is_parameter_entity || entity_name_to_match == NULL
458 || entity_value_to_match == NULL) {
459 return;
460 }
461 if (! xcstrcmp(entityName, entity_name_to_match)) {
462 /* The cast here is safe because we control the horizontal and
463 * the vertical, and we therefore know our strings are never
464 * going to overflow an int.
465 */
466 if (value_length != (int)xcstrlen(entity_value_to_match)
467 || xcstrncmp(value, entity_value_to_match, value_length)) {
468 entity_match_flag = ENTITY_MATCH_FAIL;
469 } else {
470 entity_match_flag = ENTITY_MATCH_SUCCESS;
471 }
472 }
473 /* Else leave the match flag alone */
474 }
475
476 /*
477 * Character & encoding tests.
478 */
479
START_TEST(test_nul_byte)480 START_TEST(test_nul_byte) {
481 char text[] = "<doc>\0</doc>";
482
483 /* test that a NUL byte (in US-ASCII data) is an error */
484 if (_XML_Parse_SINGLE_BYTES(g_parser, text, sizeof(text) - 1, XML_TRUE)
485 == XML_STATUS_OK)
486 fail("Parser did not report error on NUL-byte.");
487 if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
488 xml_failure(g_parser);
489 }
490 END_TEST
491
START_TEST(test_u0000_char)492 START_TEST(test_u0000_char) {
493 /* test that a NUL byte (in US-ASCII data) is an error */
494 expect_failure("<doc>�</doc>", XML_ERROR_BAD_CHAR_REF,
495 "Parser did not report error on NUL-byte.");
496 }
497 END_TEST
498
START_TEST(test_siphash_self)499 START_TEST(test_siphash_self) {
500 if (! sip24_valid())
501 fail("SipHash self-test failed");
502 }
503 END_TEST
504
START_TEST(test_siphash_spec)505 START_TEST(test_siphash_spec) {
506 /* https://131002.net/siphash/siphash.pdf (page 19, "Test values") */
507 const char message[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09"
508 "\x0a\x0b\x0c\x0d\x0e";
509 const size_t len = sizeof(message) - 1;
510 const uint64_t expected = _SIP_ULL(0xa129ca61U, 0x49be45e5U);
511 struct siphash state;
512 struct sipkey key;
513
514 sip_tokey(&key, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09"
515 "\x0a\x0b\x0c\x0d\x0e\x0f");
516 sip24_init(&state, &key);
517
518 /* Cover spread across calls */
519 sip24_update(&state, message, 4);
520 sip24_update(&state, message + 4, len - 4);
521
522 /* Cover null length */
523 sip24_update(&state, message, 0);
524
525 if (sip24_final(&state) != expected)
526 fail("sip24_final failed spec test\n");
527
528 /* Cover wrapper */
529 if (siphash24(message, len, &key) != expected)
530 fail("siphash24 failed spec test\n");
531 }
532 END_TEST
533
START_TEST(test_bom_utf8)534 START_TEST(test_bom_utf8) {
535 /* This test is really just making sure we don't core on a UTF-8 BOM. */
536 const char *text = "\357\273\277<e/>";
537
538 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
539 == XML_STATUS_ERROR)
540 xml_failure(g_parser);
541 }
542 END_TEST
543
START_TEST(test_bom_utf16_be)544 START_TEST(test_bom_utf16_be) {
545 char text[] = "\376\377\0<\0e\0/\0>";
546
547 if (_XML_Parse_SINGLE_BYTES(g_parser, text, sizeof(text) - 1, XML_TRUE)
548 == XML_STATUS_ERROR)
549 xml_failure(g_parser);
550 }
551 END_TEST
552
START_TEST(test_bom_utf16_le)553 START_TEST(test_bom_utf16_le) {
554 char text[] = "\377\376<\0e\0/\0>\0";
555
556 if (_XML_Parse_SINGLE_BYTES(g_parser, text, sizeof(text) - 1, XML_TRUE)
557 == XML_STATUS_ERROR)
558 xml_failure(g_parser);
559 }
560 END_TEST
561
562 /* Parse whole buffer at once to exercise a different code path */
START_TEST(test_nobom_utf16_le)563 START_TEST(test_nobom_utf16_le) {
564 char text[] = " \0<\0e\0/\0>\0";
565
566 if (XML_Parse(g_parser, text, sizeof(text) - 1, XML_TRUE) == XML_STATUS_ERROR)
567 xml_failure(g_parser);
568 }
569 END_TEST
570
571 static void XMLCALL
accumulate_characters(void * userData,const XML_Char * s,int len)572 accumulate_characters(void *userData, const XML_Char *s, int len) {
573 CharData_AppendXMLChars((CharData *)userData, s, len);
574 }
575
576 static void XMLCALL
accumulate_attribute(void * userData,const XML_Char * name,const XML_Char ** atts)577 accumulate_attribute(void *userData, const XML_Char *name,
578 const XML_Char **atts) {
579 CharData *storage = (CharData *)userData;
580 UNUSED_P(name);
581 /* Check there are attributes to deal with */
582 if (atts == NULL)
583 return;
584
585 while (storage->count < 0 && atts[0] != NULL) {
586 /* "accumulate" the value of the first attribute we see */
587 CharData_AppendXMLChars(storage, atts[1], -1);
588 atts += 2;
589 }
590 }
591
592 static void
_run_character_check(const char * text,const XML_Char * expected,const char * file,int line)593 _run_character_check(const char *text, const XML_Char *expected,
594 const char *file, int line) {
595 CharData storage;
596
597 CharData_Init(&storage);
598 XML_SetUserData(g_parser, &storage);
599 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
600 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
601 == XML_STATUS_ERROR)
602 _xml_failure(g_parser, file, line);
603 CharData_CheckXMLChars(&storage, expected);
604 }
605
606 #define run_character_check(text, expected) \
607 _run_character_check(text, expected, __FILE__, __LINE__)
608
609 static void
_run_attribute_check(const char * text,const XML_Char * expected,const char * file,int line)610 _run_attribute_check(const char *text, const XML_Char *expected,
611 const char *file, int line) {
612 CharData storage;
613
614 CharData_Init(&storage);
615 XML_SetUserData(g_parser, &storage);
616 XML_SetStartElementHandler(g_parser, accumulate_attribute);
617 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
618 == XML_STATUS_ERROR)
619 _xml_failure(g_parser, file, line);
620 CharData_CheckXMLChars(&storage, expected);
621 }
622
623 #define run_attribute_check(text, expected) \
624 _run_attribute_check(text, expected, __FILE__, __LINE__)
625
626 typedef struct ExtTest {
627 const char *parse_text;
628 const XML_Char *encoding;
629 CharData *storage;
630 } ExtTest;
631
632 static void XMLCALL
ext_accumulate_characters(void * userData,const XML_Char * s,int len)633 ext_accumulate_characters(void *userData, const XML_Char *s, int len) {
634 ExtTest *test_data = (ExtTest *)userData;
635 accumulate_characters(test_data->storage, s, len);
636 }
637
638 static void
_run_ext_character_check(const char * text,ExtTest * test_data,const XML_Char * expected,const char * file,int line)639 _run_ext_character_check(const char *text, ExtTest *test_data,
640 const XML_Char *expected, const char *file, int line) {
641 CharData *const storage = (CharData *)malloc(sizeof(CharData));
642
643 CharData_Init(storage);
644 test_data->storage = storage;
645 XML_SetUserData(g_parser, test_data);
646 XML_SetCharacterDataHandler(g_parser, ext_accumulate_characters);
647 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
648 == XML_STATUS_ERROR)
649 _xml_failure(g_parser, file, line);
650 CharData_CheckXMLChars(storage, expected);
651
652 free(storage);
653 }
654
655 #define run_ext_character_check(text, test_data, expected) \
656 _run_ext_character_check(text, test_data, expected, __FILE__, __LINE__)
657
658 /* Regression test for SF bug #491986. */
START_TEST(test_danish_latin1)659 START_TEST(test_danish_latin1) {
660 const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
661 "<e>J\xF8rgen \xE6\xF8\xE5\xC6\xD8\xC5</e>";
662 #ifdef XML_UNICODE
663 const XML_Char *expected
664 = XCS("J\x00f8rgen \x00e6\x00f8\x00e5\x00c6\x00d8\x00c5");
665 #else
666 const XML_Char *expected
667 = XCS("J\xC3\xB8rgen \xC3\xA6\xC3\xB8\xC3\xA5\xC3\x86\xC3\x98\xC3\x85");
668 #endif
669 run_character_check(text, expected);
670 }
671 END_TEST
672
673 /* Regression test for SF bug #514281. */
START_TEST(test_french_charref_hexidecimal)674 START_TEST(test_french_charref_hexidecimal) {
675 const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
676 "<doc>éèàçêÈ</doc>";
677 #ifdef XML_UNICODE
678 const XML_Char *expected = XCS("\x00e9\x00e8\x00e0\x00e7\x00ea\x00c8");
679 #else
680 const XML_Char *expected
681 = XCS("\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88");
682 #endif
683 run_character_check(text, expected);
684 }
685 END_TEST
686
START_TEST(test_french_charref_decimal)687 START_TEST(test_french_charref_decimal) {
688 const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
689 "<doc>éèàçêÈ</doc>";
690 #ifdef XML_UNICODE
691 const XML_Char *expected = XCS("\x00e9\x00e8\x00e0\x00e7\x00ea\x00c8");
692 #else
693 const XML_Char *expected
694 = XCS("\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88");
695 #endif
696 run_character_check(text, expected);
697 }
698 END_TEST
699
START_TEST(test_french_latin1)700 START_TEST(test_french_latin1) {
701 const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
702 "<doc>\xE9\xE8\xE0\xE7\xEa\xC8</doc>";
703 #ifdef XML_UNICODE
704 const XML_Char *expected = XCS("\x00e9\x00e8\x00e0\x00e7\x00ea\x00c8");
705 #else
706 const XML_Char *expected
707 = XCS("\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88");
708 #endif
709 run_character_check(text, expected);
710 }
711 END_TEST
712
START_TEST(test_french_utf8)713 START_TEST(test_french_utf8) {
714 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
715 "<doc>\xC3\xA9</doc>";
716 #ifdef XML_UNICODE
717 const XML_Char *expected = XCS("\x00e9");
718 #else
719 const XML_Char *expected = XCS("\xC3\xA9");
720 #endif
721 run_character_check(text, expected);
722 }
723 END_TEST
724
725 /* Regression test for SF bug #600479.
726 XXX There should be a test that exercises all legal XML Unicode
727 characters as PCDATA and attribute value content, and XML Name
728 characters as part of element and attribute names.
729 */
START_TEST(test_utf8_false_rejection)730 START_TEST(test_utf8_false_rejection) {
731 const char *text = "<doc>\xEF\xBA\xBF</doc>";
732 #ifdef XML_UNICODE
733 const XML_Char *expected = XCS("\xfebf");
734 #else
735 const XML_Char *expected = XCS("\xEF\xBA\xBF");
736 #endif
737 run_character_check(text, expected);
738 }
739 END_TEST
740
741 /* Regression test for SF bug #477667.
742 This test assures that any 8-bit character followed by a 7-bit
743 character will not be mistakenly interpreted as a valid UTF-8
744 sequence.
745 */
START_TEST(test_illegal_utf8)746 START_TEST(test_illegal_utf8) {
747 char text[100];
748 int i;
749
750 for (i = 128; i <= 255; ++i) {
751 sprintf(text, "<e>%ccd</e>", i);
752 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
753 == XML_STATUS_OK) {
754 sprintf(text, "expected token error for '%c' (ordinal %d) in UTF-8 text",
755 i, i);
756 fail(text);
757 } else if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
758 xml_failure(g_parser);
759 /* Reset the parser since we use the same parser repeatedly. */
760 XML_ParserReset(g_parser, NULL);
761 }
762 }
763 END_TEST
764
765 /* Examples, not masks: */
766 #define UTF8_LEAD_1 "\x7f" /* 0b01111111 */
767 #define UTF8_LEAD_2 "\xdf" /* 0b11011111 */
768 #define UTF8_LEAD_3 "\xef" /* 0b11101111 */
769 #define UTF8_LEAD_4 "\xf7" /* 0b11110111 */
770 #define UTF8_FOLLOW "\xbf" /* 0b10111111 */
771
START_TEST(test_utf8_auto_align)772 START_TEST(test_utf8_auto_align) {
773 struct TestCase {
774 ptrdiff_t expectedMovementInChars;
775 const char *input;
776 };
777
778 struct TestCase cases[] = {
779 {00, ""},
780
781 {00, UTF8_LEAD_1},
782
783 {-1, UTF8_LEAD_2},
784 {00, UTF8_LEAD_2 UTF8_FOLLOW},
785
786 {-1, UTF8_LEAD_3},
787 {-2, UTF8_LEAD_3 UTF8_FOLLOW},
788 {00, UTF8_LEAD_3 UTF8_FOLLOW UTF8_FOLLOW},
789
790 {-1, UTF8_LEAD_4},
791 {-2, UTF8_LEAD_4 UTF8_FOLLOW},
792 {-3, UTF8_LEAD_4 UTF8_FOLLOW UTF8_FOLLOW},
793 {00, UTF8_LEAD_4 UTF8_FOLLOW UTF8_FOLLOW UTF8_FOLLOW},
794 };
795
796 size_t i = 0;
797 bool success = true;
798 for (; i < sizeof(cases) / sizeof(*cases); i++) {
799 const char *fromLim = cases[i].input + strlen(cases[i].input);
800 const char *const fromLimInitially = fromLim;
801 ptrdiff_t actualMovementInChars;
802
803 _INTERNAL_trim_to_complete_utf8_characters(cases[i].input, &fromLim);
804
805 actualMovementInChars = (fromLim - fromLimInitially);
806 if (actualMovementInChars != cases[i].expectedMovementInChars) {
807 size_t j = 0;
808 success = false;
809 printf("[-] UTF-8 case %2u: Expected movement by %2d chars"
810 ", actually moved by %2d chars: \"",
811 (unsigned)(i + 1), (int)cases[i].expectedMovementInChars,
812 (int)actualMovementInChars);
813 for (; j < strlen(cases[i].input); j++) {
814 printf("\\x%02x", (unsigned char)cases[i].input[j]);
815 }
816 printf("\"\n");
817 }
818 }
819
820 if (! success) {
821 fail("UTF-8 auto-alignment is not bullet-proof\n");
822 }
823 }
824 END_TEST
825
START_TEST(test_utf16)826 START_TEST(test_utf16) {
827 /* <?xml version="1.0" encoding="UTF-16"?>
828 * <doc a='123'>some {A} text</doc>
829 *
830 * where {A} is U+FF21, FULLWIDTH LATIN CAPITAL LETTER A
831 */
832 char text[]
833 = "\000<\000?\000x\000m\000\154\000 \000v\000e\000r\000s\000i\000o"
834 "\000n\000=\000'\0001\000.\000\060\000'\000 \000e\000n\000c\000o"
835 "\000d\000i\000n\000g\000=\000'\000U\000T\000F\000-\0001\000\066"
836 "\000'\000?\000>\000\n"
837 "\000<\000d\000o\000c\000 \000a\000=\000'\0001\0002\0003\000'\000>"
838 "\000s\000o\000m\000e\000 \xff\x21\000 \000t\000e\000x\000t\000"
839 "<\000/\000d\000o\000c\000>";
840 #ifdef XML_UNICODE
841 const XML_Char *expected = XCS("some \xff21 text");
842 #else
843 const XML_Char *expected = XCS("some \357\274\241 text");
844 #endif
845 CharData storage;
846
847 CharData_Init(&storage);
848 XML_SetUserData(g_parser, &storage);
849 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
850 if (_XML_Parse_SINGLE_BYTES(g_parser, text, sizeof(text) - 1, XML_TRUE)
851 == XML_STATUS_ERROR)
852 xml_failure(g_parser);
853 CharData_CheckXMLChars(&storage, expected);
854 }
855 END_TEST
856
START_TEST(test_utf16_le_epilog_newline)857 START_TEST(test_utf16_le_epilog_newline) {
858 unsigned int first_chunk_bytes = 17;
859 char text[] = "\xFF\xFE" /* BOM */
860 "<\000e\000/\000>\000" /* document element */
861 "\r\000\n\000\r\000\n\000"; /* epilog */
862
863 if (first_chunk_bytes >= sizeof(text) - 1)
864 fail("bad value of first_chunk_bytes");
865 if (_XML_Parse_SINGLE_BYTES(g_parser, text, first_chunk_bytes, XML_FALSE)
866 == XML_STATUS_ERROR)
867 xml_failure(g_parser);
868 else {
869 enum XML_Status rc;
870 rc = _XML_Parse_SINGLE_BYTES(g_parser, text + first_chunk_bytes,
871 sizeof(text) - first_chunk_bytes - 1,
872 XML_TRUE);
873 if (rc == XML_STATUS_ERROR)
874 xml_failure(g_parser);
875 }
876 }
877 END_TEST
878
879 /* Test that an outright lie in the encoding is faulted */
START_TEST(test_not_utf16)880 START_TEST(test_not_utf16) {
881 const char *text = "<?xml version='1.0' encoding='utf-16'?>"
882 "<doc>Hi</doc>";
883
884 /* Use a handler to provoke the appropriate code paths */
885 XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler);
886 expect_failure(text, XML_ERROR_INCORRECT_ENCODING,
887 "UTF-16 declared in UTF-8 not faulted");
888 }
889 END_TEST
890
891 /* Test that an unknown encoding is rejected */
START_TEST(test_bad_encoding)892 START_TEST(test_bad_encoding) {
893 const char *text = "<doc>Hi</doc>";
894
895 if (! XML_SetEncoding(g_parser, XCS("unknown-encoding")))
896 fail("XML_SetEncoding failed");
897 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
898 "Unknown encoding not faulted");
899 }
900 END_TEST
901
902 /* Regression test for SF bug #481609, #774028. */
START_TEST(test_latin1_umlauts)903 START_TEST(test_latin1_umlauts) {
904 const char *text
905 = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
906 "<e a='\xE4 \xF6 \xFC ä ö ü ä ö ü >'\n"
907 " >\xE4 \xF6 \xFC ä ö ü ä ö ü ></e>";
908 #ifdef XML_UNICODE
909 /* Expected results in UTF-16 */
910 const XML_Char *expected = XCS("\x00e4 \x00f6 \x00fc ")
911 XCS("\x00e4 \x00f6 \x00fc ") XCS("\x00e4 \x00f6 \x00fc >");
912 #else
913 /* Expected results in UTF-8 */
914 const XML_Char *expected = XCS("\xC3\xA4 \xC3\xB6 \xC3\xBC ")
915 XCS("\xC3\xA4 \xC3\xB6 \xC3\xBC ") XCS("\xC3\xA4 \xC3\xB6 \xC3\xBC >");
916 #endif
917
918 run_character_check(text, expected);
919 XML_ParserReset(g_parser, NULL);
920 run_attribute_check(text, expected);
921 /* Repeat with a default handler */
922 XML_ParserReset(g_parser, NULL);
923 XML_SetDefaultHandler(g_parser, dummy_default_handler);
924 run_character_check(text, expected);
925 XML_ParserReset(g_parser, NULL);
926 XML_SetDefaultHandler(g_parser, dummy_default_handler);
927 run_attribute_check(text, expected);
928 }
929 END_TEST
930
931 /* Test that an element name with a 4-byte UTF-8 character is rejected */
START_TEST(test_long_utf8_character)932 START_TEST(test_long_utf8_character) {
933 const char *text
934 = "<?xml version='1.0' encoding='utf-8'?>\n"
935 /* 0xf0 0x90 0x80 0x80 = U+10000, the first Linear B character */
936 "<do\xf0\x90\x80\x80/>";
937 expect_failure(text, XML_ERROR_INVALID_TOKEN,
938 "4-byte UTF-8 character in element name not faulted");
939 }
940 END_TEST
941
942 /* Test that a long latin-1 attribute (too long to convert in one go)
943 * is correctly converted
944 */
START_TEST(test_long_latin1_attribute)945 START_TEST(test_long_latin1_attribute) {
946 const char *text
947 = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
948 "<doc att='"
949 /* 64 characters per line */
950 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
951 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
952 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
953 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
954 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
955 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
956 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
957 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
958 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
959 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
960 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
961 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
962 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
963 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
964 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
965 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
966 /* Last character splits across a buffer boundary */
967 "\xe4'>\n</doc>";
968
969 const XML_Char *expected =
970 /* 64 characters per line */
971 /* clang-format off */
972 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
973 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
974 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
975 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
976 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
977 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
978 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
979 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
980 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
981 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
982 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
983 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
984 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
985 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
986 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
987 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO")
988 /* clang-format on */
989 #ifdef XML_UNICODE
990 XCS("\x00e4");
991 #else
992 XCS("\xc3\xa4");
993 #endif
994
995 run_attribute_check(text, expected);
996 }
997 END_TEST
998
999 /* Test that a long ASCII attribute (too long to convert in one go)
1000 * is correctly converted
1001 */
START_TEST(test_long_ascii_attribute)1002 START_TEST(test_long_ascii_attribute) {
1003 const char *text
1004 = "<?xml version='1.0' encoding='us-ascii'?>\n"
1005 "<doc att='"
1006 /* 64 characters per line */
1007 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1008 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1009 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1010 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1011 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1012 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1013 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1014 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1015 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1016 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1017 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1018 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1019 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1020 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1021 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1022 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1023 "01234'>\n</doc>";
1024 const XML_Char *expected =
1025 /* 64 characters per line */
1026 /* clang-format off */
1027 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1028 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1029 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1030 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1031 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1032 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1033 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1034 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1035 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1036 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1037 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1038 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1039 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1040 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1041 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1042 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1043 XCS("01234");
1044 /* clang-format on */
1045
1046 run_attribute_check(text, expected);
1047 }
1048 END_TEST
1049
1050 /* Regression test #1 for SF bug #653180. */
START_TEST(test_line_number_after_parse)1051 START_TEST(test_line_number_after_parse) {
1052 const char *text = "<tag>\n"
1053 "\n"
1054 "\n</tag>";
1055 XML_Size lineno;
1056
1057 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
1058 == XML_STATUS_ERROR)
1059 xml_failure(g_parser);
1060 lineno = XML_GetCurrentLineNumber(g_parser);
1061 if (lineno != 4) {
1062 char buffer[100];
1063 sprintf(buffer, "expected 4 lines, saw %" XML_FMT_INT_MOD "u", lineno);
1064 fail(buffer);
1065 }
1066 }
1067 END_TEST
1068
1069 /* Regression test #2 for SF bug #653180. */
START_TEST(test_column_number_after_parse)1070 START_TEST(test_column_number_after_parse) {
1071 const char *text = "<tag></tag>";
1072 XML_Size colno;
1073
1074 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
1075 == XML_STATUS_ERROR)
1076 xml_failure(g_parser);
1077 colno = XML_GetCurrentColumnNumber(g_parser);
1078 if (colno != 11) {
1079 char buffer[100];
1080 sprintf(buffer, "expected 11 columns, saw %" XML_FMT_INT_MOD "u", colno);
1081 fail(buffer);
1082 }
1083 }
1084 END_TEST
1085
1086 #define STRUCT_START_TAG 0
1087 #define STRUCT_END_TAG 1
1088 static void XMLCALL
start_element_event_handler2(void * userData,const XML_Char * name,const XML_Char ** attr)1089 start_element_event_handler2(void *userData, const XML_Char *name,
1090 const XML_Char **attr) {
1091 StructData *storage = (StructData *)userData;
1092 UNUSED_P(attr);
1093 StructData_AddItem(storage, name, XML_GetCurrentColumnNumber(g_parser),
1094 XML_GetCurrentLineNumber(g_parser), STRUCT_START_TAG);
1095 }
1096
1097 static void XMLCALL
end_element_event_handler2(void * userData,const XML_Char * name)1098 end_element_event_handler2(void *userData, const XML_Char *name) {
1099 StructData *storage = (StructData *)userData;
1100 StructData_AddItem(storage, name, XML_GetCurrentColumnNumber(g_parser),
1101 XML_GetCurrentLineNumber(g_parser), STRUCT_END_TAG);
1102 }
1103
1104 /* Regression test #3 for SF bug #653180. */
START_TEST(test_line_and_column_numbers_inside_handlers)1105 START_TEST(test_line_and_column_numbers_inside_handlers) {
1106 const char *text = "<a>\n" /* Unix end-of-line */
1107 " <b>\r\n" /* Windows end-of-line */
1108 " <c/>\r" /* Mac OS end-of-line */
1109 " </b>\n"
1110 " <d>\n"
1111 " <f/>\n"
1112 " </d>\n"
1113 "</a>";
1114 const StructDataEntry expected[]
1115 = {{XCS("a"), 0, 1, STRUCT_START_TAG}, {XCS("b"), 2, 2, STRUCT_START_TAG},
1116 {XCS("c"), 4, 3, STRUCT_START_TAG}, {XCS("c"), 8, 3, STRUCT_END_TAG},
1117 {XCS("b"), 2, 4, STRUCT_END_TAG}, {XCS("d"), 2, 5, STRUCT_START_TAG},
1118 {XCS("f"), 4, 6, STRUCT_START_TAG}, {XCS("f"), 8, 6, STRUCT_END_TAG},
1119 {XCS("d"), 2, 7, STRUCT_END_TAG}, {XCS("a"), 0, 8, STRUCT_END_TAG}};
1120 const int expected_count = sizeof(expected) / sizeof(StructDataEntry);
1121 StructData storage;
1122
1123 StructData_Init(&storage);
1124 XML_SetUserData(g_parser, &storage);
1125 XML_SetStartElementHandler(g_parser, start_element_event_handler2);
1126 XML_SetEndElementHandler(g_parser, end_element_event_handler2);
1127 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1128 == XML_STATUS_ERROR)
1129 xml_failure(g_parser);
1130
1131 StructData_CheckItems(&storage, expected, expected_count);
1132 StructData_Dispose(&storage);
1133 }
1134 END_TEST
1135
1136 /* Regression test #4 for SF bug #653180. */
START_TEST(test_line_number_after_error)1137 START_TEST(test_line_number_after_error) {
1138 const char *text = "<a>\n"
1139 " <b>\n"
1140 " </a>"; /* missing </b> */
1141 XML_Size lineno;
1142 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
1143 != XML_STATUS_ERROR)
1144 fail("Expected a parse error");
1145
1146 lineno = XML_GetCurrentLineNumber(g_parser);
1147 if (lineno != 3) {
1148 char buffer[100];
1149 sprintf(buffer, "expected 3 lines, saw %" XML_FMT_INT_MOD "u", lineno);
1150 fail(buffer);
1151 }
1152 }
1153 END_TEST
1154
1155 /* Regression test #5 for SF bug #653180. */
START_TEST(test_column_number_after_error)1156 START_TEST(test_column_number_after_error) {
1157 const char *text = "<a>\n"
1158 " <b>\n"
1159 " </a>"; /* missing </b> */
1160 XML_Size colno;
1161 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
1162 != XML_STATUS_ERROR)
1163 fail("Expected a parse error");
1164
1165 colno = XML_GetCurrentColumnNumber(g_parser);
1166 if (colno != 4) {
1167 char buffer[100];
1168 sprintf(buffer, "expected 4 columns, saw %" XML_FMT_INT_MOD "u", colno);
1169 fail(buffer);
1170 }
1171 }
1172 END_TEST
1173
1174 /* Regression test for SF bug #478332. */
START_TEST(test_really_long_lines)1175 START_TEST(test_really_long_lines) {
1176 /* This parses an input line longer than INIT_DATA_BUF_SIZE
1177 characters long (defined to be 1024 in xmlparse.c). We take a
1178 really cheesy approach to building the input buffer, because
1179 this avoids writing bugs in buffer-filling code.
1180 */
1181 const char *text
1182 = "<e>"
1183 /* 64 chars */
1184 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1185 /* until we have at least 1024 characters on the line: */
1186 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1187 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1188 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1189 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1190 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1191 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1192 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1193 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1194 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1195 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1196 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1197 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1198 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1199 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1200 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1201 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1202 "</e>";
1203 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1204 == XML_STATUS_ERROR)
1205 xml_failure(g_parser);
1206 }
1207 END_TEST
1208
1209 /* Test cdata processing across a buffer boundary */
START_TEST(test_really_long_encoded_lines)1210 START_TEST(test_really_long_encoded_lines) {
1211 /* As above, except that we want to provoke an output buffer
1212 * overflow with a non-trivial encoding. For this we need to pass
1213 * the whole cdata in one go, not byte-by-byte.
1214 */
1215 void *buffer;
1216 const char *text
1217 = "<?xml version='1.0' encoding='iso-8859-1'?>"
1218 "<e>"
1219 /* 64 chars */
1220 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1221 /* until we have at least 1024 characters on the line: */
1222 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1223 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1224 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1225 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1226 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1227 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1228 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1229 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1230 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1231 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1232 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1233 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1234 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1235 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1236 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1237 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1238 "</e>";
1239 int parse_len = (int)strlen(text);
1240
1241 /* Need a cdata handler to provoke the code path we want to test */
1242 XML_SetCharacterDataHandler(g_parser, dummy_cdata_handler);
1243 buffer = XML_GetBuffer(g_parser, parse_len);
1244 if (buffer == NULL)
1245 fail("Could not allocate parse buffer");
1246 assert(buffer != NULL);
1247 memcpy(buffer, text, parse_len);
1248 if (XML_ParseBuffer(g_parser, parse_len, XML_TRUE) == XML_STATUS_ERROR)
1249 xml_failure(g_parser);
1250 }
1251 END_TEST
1252
1253 /*
1254 * Element event tests.
1255 */
1256
1257 static void XMLCALL
start_element_event_handler(void * userData,const XML_Char * name,const XML_Char ** atts)1258 start_element_event_handler(void *userData, const XML_Char *name,
1259 const XML_Char **atts) {
1260 UNUSED_P(atts);
1261 CharData_AppendXMLChars((CharData *)userData, name, -1);
1262 }
1263
1264 static void XMLCALL
end_element_event_handler(void * userData,const XML_Char * name)1265 end_element_event_handler(void *userData, const XML_Char *name) {
1266 CharData *storage = (CharData *)userData;
1267 CharData_AppendXMLChars(storage, XCS("/"), 1);
1268 CharData_AppendXMLChars(storage, name, -1);
1269 }
1270
START_TEST(test_end_element_events)1271 START_TEST(test_end_element_events) {
1272 const char *text = "<a><b><c/></b><d><f/></d></a>";
1273 const XML_Char *expected = XCS("/c/b/f/d/a");
1274 CharData storage;
1275
1276 CharData_Init(&storage);
1277 XML_SetUserData(g_parser, &storage);
1278 XML_SetEndElementHandler(g_parser, end_element_event_handler);
1279 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1280 == XML_STATUS_ERROR)
1281 xml_failure(g_parser);
1282 CharData_CheckXMLChars(&storage, expected);
1283 }
1284 END_TEST
1285
1286 /*
1287 * Attribute tests.
1288 */
1289
1290 /* Helpers used by the following test; this checks any "attr" and "refs"
1291 attributes to make sure whitespace has been normalized.
1292
1293 Return true if whitespace has been normalized in a string, using
1294 the rules for attribute value normalization. The 'is_cdata' flag
1295 is needed since CDATA attributes don't need to have multiple
1296 whitespace characters collapsed to a single space, while other
1297 attribute data types do. (Section 3.3.3 of the recommendation.)
1298 */
1299 static int
is_whitespace_normalized(const XML_Char * s,int is_cdata)1300 is_whitespace_normalized(const XML_Char *s, int is_cdata) {
1301 int blanks = 0;
1302 int at_start = 1;
1303 while (*s) {
1304 if (*s == XCS(' '))
1305 ++blanks;
1306 else if (*s == XCS('\t') || *s == XCS('\n') || *s == XCS('\r'))
1307 return 0;
1308 else {
1309 if (at_start) {
1310 at_start = 0;
1311 if (blanks && ! is_cdata)
1312 /* illegal leading blanks */
1313 return 0;
1314 } else if (blanks > 1 && ! is_cdata)
1315 return 0;
1316 blanks = 0;
1317 }
1318 ++s;
1319 }
1320 if (blanks && ! is_cdata)
1321 return 0;
1322 return 1;
1323 }
1324
1325 /* Check the attribute whitespace checker: */
1326 static void
testhelper_is_whitespace_normalized(void)1327 testhelper_is_whitespace_normalized(void) {
1328 assert(is_whitespace_normalized(XCS("abc"), 0));
1329 assert(is_whitespace_normalized(XCS("abc"), 1));
1330 assert(is_whitespace_normalized(XCS("abc def ghi"), 0));
1331 assert(is_whitespace_normalized(XCS("abc def ghi"), 1));
1332 assert(! is_whitespace_normalized(XCS(" abc def ghi"), 0));
1333 assert(is_whitespace_normalized(XCS(" abc def ghi"), 1));
1334 assert(! is_whitespace_normalized(XCS("abc def ghi"), 0));
1335 assert(is_whitespace_normalized(XCS("abc def ghi"), 1));
1336 assert(! is_whitespace_normalized(XCS("abc def ghi "), 0));
1337 assert(is_whitespace_normalized(XCS("abc def ghi "), 1));
1338 assert(! is_whitespace_normalized(XCS(" "), 0));
1339 assert(is_whitespace_normalized(XCS(" "), 1));
1340 assert(! is_whitespace_normalized(XCS("\t"), 0));
1341 assert(! is_whitespace_normalized(XCS("\t"), 1));
1342 assert(! is_whitespace_normalized(XCS("\n"), 0));
1343 assert(! is_whitespace_normalized(XCS("\n"), 1));
1344 assert(! is_whitespace_normalized(XCS("\r"), 0));
1345 assert(! is_whitespace_normalized(XCS("\r"), 1));
1346 assert(! is_whitespace_normalized(XCS("abc\t def"), 1));
1347 }
1348
1349 static void XMLCALL
check_attr_contains_normalized_whitespace(void * userData,const XML_Char * name,const XML_Char ** atts)1350 check_attr_contains_normalized_whitespace(void *userData, const XML_Char *name,
1351 const XML_Char **atts) {
1352 int i;
1353 UNUSED_P(userData);
1354 UNUSED_P(name);
1355 for (i = 0; atts[i] != NULL; i += 2) {
1356 const XML_Char *attrname = atts[i];
1357 const XML_Char *value = atts[i + 1];
1358 if (xcstrcmp(XCS("attr"), attrname) == 0
1359 || xcstrcmp(XCS("ents"), attrname) == 0
1360 || xcstrcmp(XCS("refs"), attrname) == 0) {
1361 if (! is_whitespace_normalized(value, 0)) {
1362 char buffer[256];
1363 sprintf(buffer,
1364 "attribute value not normalized: %" XML_FMT_STR
1365 "='%" XML_FMT_STR "'",
1366 attrname, value);
1367 fail(buffer);
1368 }
1369 }
1370 }
1371 }
1372
START_TEST(test_attr_whitespace_normalization)1373 START_TEST(test_attr_whitespace_normalization) {
1374 const char *text
1375 = "<!DOCTYPE doc [\n"
1376 " <!ATTLIST doc\n"
1377 " attr NMTOKENS #REQUIRED\n"
1378 " ents ENTITIES #REQUIRED\n"
1379 " refs IDREFS #REQUIRED>\n"
1380 "]>\n"
1381 "<doc attr=' a b c\t\td\te\t' refs=' id-1 \t id-2\t\t' \n"
1382 " ents=' ent-1 \t\r\n"
1383 " ent-2 ' >\n"
1384 " <e id='id-1'/>\n"
1385 " <e id='id-2'/>\n"
1386 "</doc>";
1387
1388 XML_SetStartElementHandler(g_parser,
1389 check_attr_contains_normalized_whitespace);
1390 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1391 == XML_STATUS_ERROR)
1392 xml_failure(g_parser);
1393 }
1394 END_TEST
1395
1396 /*
1397 * XML declaration tests.
1398 */
1399
START_TEST(test_xmldecl_misplaced)1400 START_TEST(test_xmldecl_misplaced) {
1401 expect_failure("\n"
1402 "<?xml version='1.0'?>\n"
1403 "<a/>",
1404 XML_ERROR_MISPLACED_XML_PI,
1405 "failed to report misplaced XML declaration");
1406 }
1407 END_TEST
1408
START_TEST(test_xmldecl_invalid)1409 START_TEST(test_xmldecl_invalid) {
1410 expect_failure("<?xml version='1.0' \xc3\xa7?>\n<doc/>", XML_ERROR_XML_DECL,
1411 "Failed to report invalid XML declaration");
1412 }
1413 END_TEST
1414
START_TEST(test_xmldecl_missing_attr)1415 START_TEST(test_xmldecl_missing_attr) {
1416 expect_failure("<?xml ='1.0'?>\n<doc/>\n", XML_ERROR_XML_DECL,
1417 "Failed to report missing XML declaration attribute");
1418 }
1419 END_TEST
1420
START_TEST(test_xmldecl_missing_value)1421 START_TEST(test_xmldecl_missing_value) {
1422 expect_failure("<?xml version='1.0' encoding='us-ascii' standalone?>\n"
1423 "<doc/>",
1424 XML_ERROR_XML_DECL,
1425 "Failed to report missing attribute value");
1426 }
1427 END_TEST
1428
1429 /* Regression test for SF bug #584832. */
1430 static int XMLCALL
UnknownEncodingHandler(void * data,const XML_Char * encoding,XML_Encoding * info)1431 UnknownEncodingHandler(void *data, const XML_Char *encoding,
1432 XML_Encoding *info) {
1433 UNUSED_P(data);
1434 if (xcstrcmp(encoding, XCS("unsupported-encoding")) == 0) {
1435 int i;
1436 for (i = 0; i < 256; ++i)
1437 info->map[i] = i;
1438 info->data = NULL;
1439 info->convert = NULL;
1440 info->release = NULL;
1441 return XML_STATUS_OK;
1442 }
1443 return XML_STATUS_ERROR;
1444 }
1445
START_TEST(test_unknown_encoding_internal_entity)1446 START_TEST(test_unknown_encoding_internal_entity) {
1447 const char *text = "<?xml version='1.0' encoding='unsupported-encoding'?>\n"
1448 "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n"
1449 "<test a='&foo;'/>";
1450
1451 XML_SetUnknownEncodingHandler(g_parser, UnknownEncodingHandler, NULL);
1452 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1453 == XML_STATUS_ERROR)
1454 xml_failure(g_parser);
1455 }
1456 END_TEST
1457
1458 /* Test unrecognised encoding handler */
1459 static void
dummy_release(void * data)1460 dummy_release(void *data) {
1461 UNUSED_P(data);
1462 }
1463
1464 static int XMLCALL
UnrecognisedEncodingHandler(void * data,const XML_Char * encoding,XML_Encoding * info)1465 UnrecognisedEncodingHandler(void *data, const XML_Char *encoding,
1466 XML_Encoding *info) {
1467 UNUSED_P(data);
1468 UNUSED_P(encoding);
1469 info->data = NULL;
1470 info->convert = NULL;
1471 info->release = dummy_release;
1472 return XML_STATUS_ERROR;
1473 }
1474
START_TEST(test_unrecognised_encoding_internal_entity)1475 START_TEST(test_unrecognised_encoding_internal_entity) {
1476 const char *text = "<?xml version='1.0' encoding='unsupported-encoding'?>\n"
1477 "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n"
1478 "<test a='&foo;'/>";
1479
1480 XML_SetUnknownEncodingHandler(g_parser, UnrecognisedEncodingHandler, NULL);
1481 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1482 != XML_STATUS_ERROR)
1483 fail("Unrecognised encoding not rejected");
1484 }
1485 END_TEST
1486
1487 /* Regression test for SF bug #620106. */
1488 static int XMLCALL
external_entity_loader(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)1489 external_entity_loader(XML_Parser parser, const XML_Char *context,
1490 const XML_Char *base, const XML_Char *systemId,
1491 const XML_Char *publicId) {
1492 ExtTest *test_data = (ExtTest *)XML_GetUserData(parser);
1493 XML_Parser extparser;
1494
1495 UNUSED_P(base);
1496 UNUSED_P(systemId);
1497 UNUSED_P(publicId);
1498 extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
1499 if (extparser == NULL)
1500 fail("Could not create external entity parser.");
1501 if (test_data->encoding != NULL) {
1502 if (! XML_SetEncoding(extparser, test_data->encoding))
1503 fail("XML_SetEncoding() ignored for external entity");
1504 }
1505 if (_XML_Parse_SINGLE_BYTES(extparser, test_data->parse_text,
1506 (int)strlen(test_data->parse_text), XML_TRUE)
1507 == XML_STATUS_ERROR) {
1508 xml_failure(extparser);
1509 return XML_STATUS_ERROR;
1510 }
1511 XML_ParserFree(extparser);
1512 return XML_STATUS_OK;
1513 }
1514
START_TEST(test_ext_entity_set_encoding)1515 START_TEST(test_ext_entity_set_encoding) {
1516 const char *text = "<!DOCTYPE doc [\n"
1517 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1518 "]>\n"
1519 "<doc>&en;</doc>";
1520 ExtTest test_data
1521 = {/* This text says it's an unsupported encoding, but it's really
1522 UTF-8, which we tell Expat using XML_SetEncoding().
1523 */
1524 "<?xml encoding='iso-8859-3'?>\xC3\xA9", XCS("utf-8"), NULL};
1525 #ifdef XML_UNICODE
1526 const XML_Char *expected = XCS("\x00e9");
1527 #else
1528 const XML_Char *expected = XCS("\xc3\xa9");
1529 #endif
1530
1531 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1532 run_ext_character_check(text, &test_data, expected);
1533 }
1534 END_TEST
1535
1536 /* Test external entities with no handler */
START_TEST(test_ext_entity_no_handler)1537 START_TEST(test_ext_entity_no_handler) {
1538 const char *text = "<!DOCTYPE doc [\n"
1539 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1540 "]>\n"
1541 "<doc>&en;</doc>";
1542
1543 XML_SetDefaultHandler(g_parser, dummy_default_handler);
1544 run_character_check(text, XCS(""));
1545 }
1546 END_TEST
1547
1548 /* Test UTF-8 BOM is accepted */
START_TEST(test_ext_entity_set_bom)1549 START_TEST(test_ext_entity_set_bom) {
1550 const char *text = "<!DOCTYPE doc [\n"
1551 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1552 "]>\n"
1553 "<doc>&en;</doc>";
1554 ExtTest test_data = {"\xEF\xBB\xBF" /* BOM */
1555 "<?xml encoding='iso-8859-3'?>"
1556 "\xC3\xA9",
1557 XCS("utf-8"), NULL};
1558 #ifdef XML_UNICODE
1559 const XML_Char *expected = XCS("\x00e9");
1560 #else
1561 const XML_Char *expected = XCS("\xc3\xa9");
1562 #endif
1563
1564 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1565 run_ext_character_check(text, &test_data, expected);
1566 }
1567 END_TEST
1568
1569 /* Test that bad encodings are faulted */
1570 typedef struct ext_faults {
1571 const char *parse_text;
1572 const char *fail_text;
1573 const XML_Char *encoding;
1574 enum XML_Error error;
1575 } ExtFaults;
1576
1577 static int XMLCALL
external_entity_faulter(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)1578 external_entity_faulter(XML_Parser parser, const XML_Char *context,
1579 const XML_Char *base, const XML_Char *systemId,
1580 const XML_Char *publicId) {
1581 XML_Parser ext_parser;
1582 ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser);
1583
1584 UNUSED_P(base);
1585 UNUSED_P(systemId);
1586 UNUSED_P(publicId);
1587 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
1588 if (ext_parser == NULL)
1589 fail("Could not create external entity parser");
1590 if (fault->encoding != NULL) {
1591 if (! XML_SetEncoding(ext_parser, fault->encoding))
1592 fail("XML_SetEncoding failed");
1593 }
1594 if (_XML_Parse_SINGLE_BYTES(ext_parser, fault->parse_text,
1595 (int)strlen(fault->parse_text), XML_TRUE)
1596 != XML_STATUS_ERROR)
1597 fail(fault->fail_text);
1598 if (XML_GetErrorCode(ext_parser) != fault->error)
1599 xml_failure(ext_parser);
1600
1601 XML_ParserFree(ext_parser);
1602 return XML_STATUS_ERROR;
1603 }
1604
START_TEST(test_ext_entity_bad_encoding)1605 START_TEST(test_ext_entity_bad_encoding) {
1606 const char *text = "<!DOCTYPE doc [\n"
1607 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1608 "]>\n"
1609 "<doc>&en;</doc>";
1610 ExtFaults fault
1611 = {"<?xml encoding='iso-8859-3'?>u", "Unsupported encoding not faulted",
1612 XCS("unknown"), XML_ERROR_UNKNOWN_ENCODING};
1613
1614 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
1615 XML_SetUserData(g_parser, &fault);
1616 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
1617 "Bad encoding should not have been accepted");
1618 }
1619 END_TEST
1620
1621 /* Try handing an invalid encoding to an external entity parser */
START_TEST(test_ext_entity_bad_encoding_2)1622 START_TEST(test_ext_entity_bad_encoding_2) {
1623 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
1624 "<!DOCTYPE doc SYSTEM 'foo'>\n"
1625 "<doc>&entity;</doc>";
1626 ExtFaults fault
1627 = {"<!ELEMENT doc (#PCDATA)*>", "Unknown encoding not faulted",
1628 XCS("unknown-encoding"), XML_ERROR_UNKNOWN_ENCODING};
1629
1630 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1631 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
1632 XML_SetUserData(g_parser, &fault);
1633 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
1634 "Bad encoding not faulted in external entity handler");
1635 }
1636 END_TEST
1637
1638 /* Test that no error is reported for unknown entities if we don't
1639 read an external subset. This was fixed in Expat 1.95.5.
1640 */
START_TEST(test_wfc_undeclared_entity_unread_external_subset)1641 START_TEST(test_wfc_undeclared_entity_unread_external_subset) {
1642 const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
1643 "<doc>&entity;</doc>";
1644
1645 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1646 == XML_STATUS_ERROR)
1647 xml_failure(g_parser);
1648 }
1649 END_TEST
1650
1651 /* Test that an error is reported for unknown entities if we don't
1652 have an external subset.
1653 */
START_TEST(test_wfc_undeclared_entity_no_external_subset)1654 START_TEST(test_wfc_undeclared_entity_no_external_subset) {
1655 expect_failure("<doc>&entity;</doc>", XML_ERROR_UNDEFINED_ENTITY,
1656 "Parser did not report undefined entity w/out a DTD.");
1657 }
1658 END_TEST
1659
1660 /* Test that an error is reported for unknown entities if we don't
1661 read an external subset, but have been declared standalone.
1662 */
START_TEST(test_wfc_undeclared_entity_standalone)1663 START_TEST(test_wfc_undeclared_entity_standalone) {
1664 const char *text
1665 = "<?xml version='1.0' encoding='us-ascii' standalone='yes'?>\n"
1666 "<!DOCTYPE doc SYSTEM 'foo'>\n"
1667 "<doc>&entity;</doc>";
1668
1669 expect_failure(text, XML_ERROR_UNDEFINED_ENTITY,
1670 "Parser did not report undefined entity (standalone).");
1671 }
1672 END_TEST
1673
1674 /* Test that an error is reported for unknown entities if we have read
1675 an external subset, and standalone is true.
1676 */
START_TEST(test_wfc_undeclared_entity_with_external_subset_standalone)1677 START_TEST(test_wfc_undeclared_entity_with_external_subset_standalone) {
1678 const char *text
1679 = "<?xml version='1.0' encoding='us-ascii' standalone='yes'?>\n"
1680 "<!DOCTYPE doc SYSTEM 'foo'>\n"
1681 "<doc>&entity;</doc>";
1682 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
1683
1684 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1685 XML_SetUserData(g_parser, &test_data);
1686 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1687 expect_failure(text, XML_ERROR_UNDEFINED_ENTITY,
1688 "Parser did not report undefined entity (external DTD).");
1689 }
1690 END_TEST
1691
1692 /* Test that external entity handling is not done if the parsing flag
1693 * is set to UNLESS_STANDALONE
1694 */
START_TEST(test_entity_with_external_subset_unless_standalone)1695 START_TEST(test_entity_with_external_subset_unless_standalone) {
1696 const char *text
1697 = "<?xml version='1.0' encoding='us-ascii' standalone='yes'?>\n"
1698 "<!DOCTYPE doc SYSTEM 'foo'>\n"
1699 "<doc>&entity;</doc>";
1700 ExtTest test_data = {"<!ENTITY entity 'bar'>", NULL, NULL};
1701
1702 XML_SetParamEntityParsing(g_parser,
1703 XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE);
1704 XML_SetUserData(g_parser, &test_data);
1705 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1706 expect_failure(text, XML_ERROR_UNDEFINED_ENTITY,
1707 "Parser did not report undefined entity");
1708 }
1709 END_TEST
1710
1711 /* Test that no error is reported for unknown entities if we have read
1712 an external subset, and standalone is false.
1713 */
START_TEST(test_wfc_undeclared_entity_with_external_subset)1714 START_TEST(test_wfc_undeclared_entity_with_external_subset) {
1715 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
1716 "<!DOCTYPE doc SYSTEM 'foo'>\n"
1717 "<doc>&entity;</doc>";
1718 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
1719
1720 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1721 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1722 run_ext_character_check(text, &test_data, XCS(""));
1723 }
1724 END_TEST
1725
1726 /* Test that an error is reported if our NotStandalone handler fails */
1727 static int XMLCALL
reject_not_standalone_handler(void * userData)1728 reject_not_standalone_handler(void *userData) {
1729 UNUSED_P(userData);
1730 return XML_STATUS_ERROR;
1731 }
1732
START_TEST(test_not_standalone_handler_reject)1733 START_TEST(test_not_standalone_handler_reject) {
1734 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
1735 "<!DOCTYPE doc SYSTEM 'foo'>\n"
1736 "<doc>&entity;</doc>";
1737 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
1738
1739 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1740 XML_SetUserData(g_parser, &test_data);
1741 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1742 XML_SetNotStandaloneHandler(g_parser, reject_not_standalone_handler);
1743 expect_failure(text, XML_ERROR_NOT_STANDALONE,
1744 "NotStandalone handler failed to reject");
1745
1746 /* Try again but without external entity handling */
1747 XML_ParserReset(g_parser, NULL);
1748 XML_SetNotStandaloneHandler(g_parser, reject_not_standalone_handler);
1749 expect_failure(text, XML_ERROR_NOT_STANDALONE,
1750 "NotStandalone handler failed to reject");
1751 }
1752 END_TEST
1753
1754 /* Test that no error is reported if our NotStandalone handler succeeds */
1755 static int XMLCALL
accept_not_standalone_handler(void * userData)1756 accept_not_standalone_handler(void *userData) {
1757 UNUSED_P(userData);
1758 return XML_STATUS_OK;
1759 }
1760
START_TEST(test_not_standalone_handler_accept)1761 START_TEST(test_not_standalone_handler_accept) {
1762 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
1763 "<!DOCTYPE doc SYSTEM 'foo'>\n"
1764 "<doc>&entity;</doc>";
1765 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
1766
1767 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1768 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1769 XML_SetNotStandaloneHandler(g_parser, accept_not_standalone_handler);
1770 run_ext_character_check(text, &test_data, XCS(""));
1771
1772 /* Repeat without the external entity handler */
1773 XML_ParserReset(g_parser, NULL);
1774 XML_SetNotStandaloneHandler(g_parser, accept_not_standalone_handler);
1775 run_character_check(text, XCS(""));
1776 }
1777 END_TEST
1778
START_TEST(test_wfc_no_recursive_entity_refs)1779 START_TEST(test_wfc_no_recursive_entity_refs) {
1780 const char *text = "<!DOCTYPE doc [\n"
1781 " <!ENTITY entity '&entity;'>\n"
1782 "]>\n"
1783 "<doc>&entity;</doc>";
1784
1785 expect_failure(text, XML_ERROR_RECURSIVE_ENTITY_REF,
1786 "Parser did not report recursive entity reference.");
1787 }
1788 END_TEST
1789
1790 /* Test incomplete external entities are faulted */
START_TEST(test_ext_entity_invalid_parse)1791 START_TEST(test_ext_entity_invalid_parse) {
1792 const char *text = "<!DOCTYPE doc [\n"
1793 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1794 "]>\n"
1795 "<doc>&en;</doc>";
1796 const ExtFaults faults[]
1797 = {{"<", "Incomplete element declaration not faulted", NULL,
1798 XML_ERROR_UNCLOSED_TOKEN},
1799 {"<\xe2\x82", /* First two bytes of a three-byte char */
1800 "Incomplete character not faulted", NULL, XML_ERROR_PARTIAL_CHAR},
1801 {"<tag>\xe2\x82", "Incomplete character in CDATA not faulted", NULL,
1802 XML_ERROR_PARTIAL_CHAR},
1803 {NULL, NULL, NULL, XML_ERROR_NONE}};
1804 const ExtFaults *fault = faults;
1805
1806 for (; fault->parse_text != NULL; fault++) {
1807 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1808 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
1809 XML_SetUserData(g_parser, (void *)fault);
1810 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
1811 "Parser did not report external entity error");
1812 XML_ParserReset(g_parser, NULL);
1813 }
1814 }
1815 END_TEST
1816
1817 /* Regression test for SF bug #483514. */
START_TEST(test_dtd_default_handling)1818 START_TEST(test_dtd_default_handling) {
1819 const char *text = "<!DOCTYPE doc [\n"
1820 "<!ENTITY e SYSTEM 'http://example.org/e'>\n"
1821 "<!NOTATION n SYSTEM 'http://example.org/n'>\n"
1822 "<!ELEMENT doc EMPTY>\n"
1823 "<!ATTLIST doc a CDATA #IMPLIED>\n"
1824 "<?pi in dtd?>\n"
1825 "<!--comment in dtd-->\n"
1826 "]><doc/>";
1827
1828 XML_SetDefaultHandler(g_parser, accumulate_characters);
1829 XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler);
1830 XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler);
1831 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
1832 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
1833 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
1834 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
1835 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
1836 XML_SetCommentHandler(g_parser, dummy_comment_handler);
1837 XML_SetStartCdataSectionHandler(g_parser, dummy_start_cdata_handler);
1838 XML_SetEndCdataSectionHandler(g_parser, dummy_end_cdata_handler);
1839 run_character_check(text, XCS("\n\n\n\n\n\n\n<doc/>"));
1840 }
1841 END_TEST
1842
1843 /* Test handling of attribute declarations */
1844 typedef struct AttTest {
1845 const char *definition;
1846 const XML_Char *element_name;
1847 const XML_Char *attr_name;
1848 const XML_Char *attr_type;
1849 const XML_Char *default_value;
1850 int is_required;
1851 } AttTest;
1852
1853 static void XMLCALL
verify_attlist_decl_handler(void * userData,const XML_Char * element_name,const XML_Char * attr_name,const XML_Char * attr_type,const XML_Char * default_value,int is_required)1854 verify_attlist_decl_handler(void *userData, const XML_Char *element_name,
1855 const XML_Char *attr_name,
1856 const XML_Char *attr_type,
1857 const XML_Char *default_value, int is_required) {
1858 AttTest *at = (AttTest *)userData;
1859
1860 if (xcstrcmp(element_name, at->element_name))
1861 fail("Unexpected element name in attribute declaration");
1862 if (xcstrcmp(attr_name, at->attr_name))
1863 fail("Unexpected attribute name in attribute declaration");
1864 if (xcstrcmp(attr_type, at->attr_type))
1865 fail("Unexpected attribute type in attribute declaration");
1866 if ((default_value == NULL && at->default_value != NULL)
1867 || (default_value != NULL && at->default_value == NULL)
1868 || (default_value != NULL && xcstrcmp(default_value, at->default_value)))
1869 fail("Unexpected default value in attribute declaration");
1870 if (is_required != at->is_required)
1871 fail("Requirement mismatch in attribute declaration");
1872 }
1873
START_TEST(test_dtd_attr_handling)1874 START_TEST(test_dtd_attr_handling) {
1875 const char *prolog = "<!DOCTYPE doc [\n"
1876 "<!ELEMENT doc EMPTY>\n";
1877 AttTest attr_data[]
1878 = {{"<!ATTLIST doc a ( one | two | three ) #REQUIRED>\n"
1879 "]>"
1880 "<doc a='two'/>",
1881 XCS("doc"), XCS("a"),
1882 XCS("(one|two|three)"), /* Extraneous spaces will be removed */
1883 NULL, XML_TRUE},
1884 {"<!NOTATION foo SYSTEM 'http://example.org/foo'>\n"
1885 "<!ATTLIST doc a NOTATION (foo) #IMPLIED>\n"
1886 "]>"
1887 "<doc/>",
1888 XCS("doc"), XCS("a"), XCS("NOTATION(foo)"), NULL, XML_FALSE},
1889 {"<!ATTLIST doc a NOTATION (foo) 'bar'>\n"
1890 "]>"
1891 "<doc/>",
1892 XCS("doc"), XCS("a"), XCS("NOTATION(foo)"), XCS("bar"), XML_FALSE},
1893 {"<!ATTLIST doc a CDATA '\xdb\xb2'>\n"
1894 "]>"
1895 "<doc/>",
1896 XCS("doc"), XCS("a"), XCS("CDATA"),
1897 #ifdef XML_UNICODE
1898 XCS("\x06f2"),
1899 #else
1900 XCS("\xdb\xb2"),
1901 #endif
1902 XML_FALSE},
1903 {NULL, NULL, NULL, NULL, NULL, XML_FALSE}};
1904 AttTest *test;
1905
1906 for (test = attr_data; test->definition != NULL; test++) {
1907 XML_SetAttlistDeclHandler(g_parser, verify_attlist_decl_handler);
1908 XML_SetUserData(g_parser, test);
1909 if (_XML_Parse_SINGLE_BYTES(g_parser, prolog, (int)strlen(prolog),
1910 XML_FALSE)
1911 == XML_STATUS_ERROR)
1912 xml_failure(g_parser);
1913 if (_XML_Parse_SINGLE_BYTES(g_parser, test->definition,
1914 (int)strlen(test->definition), XML_TRUE)
1915 == XML_STATUS_ERROR)
1916 xml_failure(g_parser);
1917 XML_ParserReset(g_parser, NULL);
1918 }
1919 }
1920 END_TEST
1921
1922 /* See related SF bug #673791.
1923 When namespace processing is enabled, setting the namespace URI for
1924 a prefix is not allowed; this test ensures that it *is* allowed
1925 when namespace processing is not enabled.
1926 (See Namespaces in XML, section 2.)
1927 */
START_TEST(test_empty_ns_without_namespaces)1928 START_TEST(test_empty_ns_without_namespaces) {
1929 const char *text = "<doc xmlns:prefix='http://example.org/'>\n"
1930 " <e xmlns:prefix=''/>\n"
1931 "</doc>";
1932
1933 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1934 == XML_STATUS_ERROR)
1935 xml_failure(g_parser);
1936 }
1937 END_TEST
1938
1939 /* Regression test for SF bug #824420.
1940 Checks that an xmlns:prefix attribute set in an attribute's default
1941 value isn't misinterpreted.
1942 */
START_TEST(test_ns_in_attribute_default_without_namespaces)1943 START_TEST(test_ns_in_attribute_default_without_namespaces) {
1944 const char *text = "<!DOCTYPE e:element [\n"
1945 " <!ATTLIST e:element\n"
1946 " xmlns:e CDATA 'http://example.org/'>\n"
1947 " ]>\n"
1948 "<e:element/>";
1949
1950 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1951 == XML_STATUS_ERROR)
1952 xml_failure(g_parser);
1953 }
1954 END_TEST
1955
1956 static const char *long_character_data_text
1957 = "<?xml version='1.0' encoding='iso-8859-1'?><s>"
1958 "012345678901234567890123456789012345678901234567890123456789"
1959 "012345678901234567890123456789012345678901234567890123456789"
1960 "012345678901234567890123456789012345678901234567890123456789"
1961 "012345678901234567890123456789012345678901234567890123456789"
1962 "012345678901234567890123456789012345678901234567890123456789"
1963 "012345678901234567890123456789012345678901234567890123456789"
1964 "012345678901234567890123456789012345678901234567890123456789"
1965 "012345678901234567890123456789012345678901234567890123456789"
1966 "012345678901234567890123456789012345678901234567890123456789"
1967 "012345678901234567890123456789012345678901234567890123456789"
1968 "012345678901234567890123456789012345678901234567890123456789"
1969 "012345678901234567890123456789012345678901234567890123456789"
1970 "012345678901234567890123456789012345678901234567890123456789"
1971 "012345678901234567890123456789012345678901234567890123456789"
1972 "012345678901234567890123456789012345678901234567890123456789"
1973 "012345678901234567890123456789012345678901234567890123456789"
1974 "012345678901234567890123456789012345678901234567890123456789"
1975 "012345678901234567890123456789012345678901234567890123456789"
1976 "012345678901234567890123456789012345678901234567890123456789"
1977 "012345678901234567890123456789012345678901234567890123456789"
1978 "</s>";
1979
1980 static XML_Bool resumable = XML_FALSE;
1981
1982 static void
clearing_aborting_character_handler(void * userData,const XML_Char * s,int len)1983 clearing_aborting_character_handler(void *userData, const XML_Char *s,
1984 int len) {
1985 UNUSED_P(userData);
1986 UNUSED_P(s);
1987 UNUSED_P(len);
1988 XML_StopParser(g_parser, resumable);
1989 XML_SetCharacterDataHandler(g_parser, NULL);
1990 }
1991
1992 /* Regression test for SF bug #1515266: missing check of stopped
1993 parser in doContext() 'for' loop. */
START_TEST(test_stop_parser_between_char_data_calls)1994 START_TEST(test_stop_parser_between_char_data_calls) {
1995 /* The sample data must be big enough that there are two calls to
1996 the character data handler from within the inner "for" loop of
1997 the XML_TOK_DATA_CHARS case in doContent(), and the character
1998 handler must stop the parser and clear the character data
1999 handler.
2000 */
2001 const char *text = long_character_data_text;
2002
2003 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2004 resumable = XML_FALSE;
2005 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2006 != XML_STATUS_ERROR)
2007 xml_failure(g_parser);
2008 if (XML_GetErrorCode(g_parser) != XML_ERROR_ABORTED)
2009 xml_failure(g_parser);
2010 }
2011 END_TEST
2012
2013 /* Regression test for SF bug #1515266: missing check of stopped
2014 parser in doContext() 'for' loop. */
START_TEST(test_suspend_parser_between_char_data_calls)2015 START_TEST(test_suspend_parser_between_char_data_calls) {
2016 /* The sample data must be big enough that there are two calls to
2017 the character data handler from within the inner "for" loop of
2018 the XML_TOK_DATA_CHARS case in doContent(), and the character
2019 handler must stop the parser and clear the character data
2020 handler.
2021 */
2022 const char *text = long_character_data_text;
2023
2024 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2025 resumable = XML_TRUE;
2026 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2027 != XML_STATUS_SUSPENDED)
2028 xml_failure(g_parser);
2029 if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE)
2030 xml_failure(g_parser);
2031 /* Try parsing directly */
2032 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
2033 != XML_STATUS_ERROR)
2034 fail("Attempt to continue parse while suspended not faulted");
2035 if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED)
2036 fail("Suspended parse not faulted with correct error");
2037 }
2038 END_TEST
2039
2040 static XML_Bool abortable = XML_FALSE;
2041
2042 static void
parser_stop_character_handler(void * userData,const XML_Char * s,int len)2043 parser_stop_character_handler(void *userData, const XML_Char *s, int len) {
2044 UNUSED_P(userData);
2045 UNUSED_P(s);
2046 UNUSED_P(len);
2047 XML_StopParser(g_parser, resumable);
2048 XML_SetCharacterDataHandler(g_parser, NULL);
2049 if (! resumable) {
2050 /* Check that aborting an aborted parser is faulted */
2051 if (XML_StopParser(g_parser, XML_FALSE) != XML_STATUS_ERROR)
2052 fail("Aborting aborted parser not faulted");
2053 if (XML_GetErrorCode(g_parser) != XML_ERROR_FINISHED)
2054 xml_failure(g_parser);
2055 } else if (abortable) {
2056 /* Check that aborting a suspended parser works */
2057 if (XML_StopParser(g_parser, XML_FALSE) == XML_STATUS_ERROR)
2058 xml_failure(g_parser);
2059 } else {
2060 /* Check that suspending a suspended parser works */
2061 if (XML_StopParser(g_parser, XML_TRUE) != XML_STATUS_ERROR)
2062 fail("Suspending suspended parser not faulted");
2063 if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED)
2064 xml_failure(g_parser);
2065 }
2066 }
2067
2068 /* Test repeated calls to XML_StopParser are handled correctly */
START_TEST(test_repeated_stop_parser_between_char_data_calls)2069 START_TEST(test_repeated_stop_parser_between_char_data_calls) {
2070 const char *text = long_character_data_text;
2071
2072 XML_SetCharacterDataHandler(g_parser, parser_stop_character_handler);
2073 resumable = XML_FALSE;
2074 abortable = XML_FALSE;
2075 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2076 != XML_STATUS_ERROR)
2077 fail("Failed to double-stop parser");
2078
2079 XML_ParserReset(g_parser, NULL);
2080 XML_SetCharacterDataHandler(g_parser, parser_stop_character_handler);
2081 resumable = XML_TRUE;
2082 abortable = XML_FALSE;
2083 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2084 != XML_STATUS_SUSPENDED)
2085 fail("Failed to double-suspend parser");
2086
2087 XML_ParserReset(g_parser, NULL);
2088 XML_SetCharacterDataHandler(g_parser, parser_stop_character_handler);
2089 resumable = XML_TRUE;
2090 abortable = XML_TRUE;
2091 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2092 != XML_STATUS_ERROR)
2093 fail("Failed to suspend-abort parser");
2094 }
2095 END_TEST
2096
START_TEST(test_good_cdata_ascii)2097 START_TEST(test_good_cdata_ascii) {
2098 const char *text = "<a><![CDATA[<greeting>Hello, world!</greeting>]]></a>";
2099 const XML_Char *expected = XCS("<greeting>Hello, world!</greeting>");
2100
2101 CharData storage;
2102 CharData_Init(&storage);
2103 XML_SetUserData(g_parser, &storage);
2104 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2105 /* Add start and end handlers for coverage */
2106 XML_SetStartCdataSectionHandler(g_parser, dummy_start_cdata_handler);
2107 XML_SetEndCdataSectionHandler(g_parser, dummy_end_cdata_handler);
2108
2109 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2110 == XML_STATUS_ERROR)
2111 xml_failure(g_parser);
2112 CharData_CheckXMLChars(&storage, expected);
2113
2114 /* Try again, this time with a default handler */
2115 XML_ParserReset(g_parser, NULL);
2116 CharData_Init(&storage);
2117 XML_SetUserData(g_parser, &storage);
2118 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2119 XML_SetDefaultHandler(g_parser, dummy_default_handler);
2120
2121 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2122 == XML_STATUS_ERROR)
2123 xml_failure(g_parser);
2124 CharData_CheckXMLChars(&storage, expected);
2125 }
2126 END_TEST
2127
START_TEST(test_good_cdata_utf16)2128 START_TEST(test_good_cdata_utf16) {
2129 /* Test data is:
2130 * <?xml version='1.0' encoding='utf-16'?>
2131 * <a><![CDATA[hello]]></a>
2132 */
2133 const char text[]
2134 = "\0<\0?\0x\0m\0l\0"
2135 " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2136 " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0"
2137 "1\0"
2138 "6\0'"
2139 "\0?\0>\0\n"
2140 "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0[\0h\0e\0l\0l\0o\0]\0]\0>\0<\0/\0a\0>";
2141 const XML_Char *expected = XCS("hello");
2142
2143 CharData storage;
2144 CharData_Init(&storage);
2145 XML_SetUserData(g_parser, &storage);
2146 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2147
2148 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
2149 == XML_STATUS_ERROR)
2150 xml_failure(g_parser);
2151 CharData_CheckXMLChars(&storage, expected);
2152 }
2153 END_TEST
2154
START_TEST(test_good_cdata_utf16_le)2155 START_TEST(test_good_cdata_utf16_le) {
2156 /* Test data is:
2157 * <?xml version='1.0' encoding='utf-16'?>
2158 * <a><![CDATA[hello]]></a>
2159 */
2160 const char text[]
2161 = "<\0?\0x\0m\0l\0"
2162 " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2163 " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0"
2164 "1\0"
2165 "6\0'"
2166 "\0?\0>\0\n"
2167 "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0[\0h\0e\0l\0l\0o\0]\0]\0>\0<\0/\0a\0>\0";
2168 const XML_Char *expected = XCS("hello");
2169
2170 CharData storage;
2171 CharData_Init(&storage);
2172 XML_SetUserData(g_parser, &storage);
2173 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2174
2175 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
2176 == XML_STATUS_ERROR)
2177 xml_failure(g_parser);
2178 CharData_CheckXMLChars(&storage, expected);
2179 }
2180 END_TEST
2181
2182 /* Test UTF16 conversion of a long cdata string */
2183
2184 /* 16 characters: handy macro to reduce visual clutter */
2185 #define A_TO_P_IN_UTF16 "\0A\0B\0C\0D\0E\0F\0G\0H\0I\0J\0K\0L\0M\0N\0O\0P"
2186
START_TEST(test_long_cdata_utf16)2187 START_TEST(test_long_cdata_utf16) {
2188 /* Test data is:
2189 * <?xlm version='1.0' encoding='utf-16'?>
2190 * <a><![CDATA[
2191 * ABCDEFGHIJKLMNOP
2192 * ]]></a>
2193 */
2194 const char text[]
2195 = "\0<\0?\0x\0m\0l\0 "
2196 "\0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0 "
2197 "\0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0\x31\0\x36\0'\0?\0>"
2198 "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0["
2199 /* 64 characters per line */
2200 /* clang-format off */
2201 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
2202 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
2203 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
2204 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
2205 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
2206 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
2207 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
2208 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
2209 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
2210 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
2211 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
2212 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
2213 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
2214 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
2215 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
2216 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
2217 A_TO_P_IN_UTF16
2218 /* clang-format on */
2219 "\0]\0]\0>\0<\0/\0a\0>";
2220 const XML_Char *expected =
2221 /* clang-format off */
2222 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2223 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2224 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2225 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2226 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2227 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2228 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2229 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2230 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2231 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2232 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2233 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2234 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2235 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2236 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2237 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2238 XCS("ABCDEFGHIJKLMNOP");
2239 /* clang-format on */
2240 CharData storage;
2241 void *buffer;
2242
2243 CharData_Init(&storage);
2244 XML_SetUserData(g_parser, &storage);
2245 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2246 buffer = XML_GetBuffer(g_parser, sizeof(text) - 1);
2247 if (buffer == NULL)
2248 fail("Could not allocate parse buffer");
2249 assert(buffer != NULL);
2250 memcpy(buffer, text, sizeof(text) - 1);
2251 if (XML_ParseBuffer(g_parser, sizeof(text) - 1, XML_TRUE) == XML_STATUS_ERROR)
2252 xml_failure(g_parser);
2253 CharData_CheckXMLChars(&storage, expected);
2254 }
2255 END_TEST
2256
2257 /* Test handling of multiple unit UTF-16 characters */
START_TEST(test_multichar_cdata_utf16)2258 START_TEST(test_multichar_cdata_utf16) {
2259 /* Test data is:
2260 * <?xml version='1.0' encoding='utf-16'?>
2261 * <a><![CDATA[{MINIM}{CROTCHET}]]></a>
2262 *
2263 * where {MINIM} is U+1d15e (a minim or half-note)
2264 * UTF-16: 0xd834 0xdd5e
2265 * UTF-8: 0xf0 0x9d 0x85 0x9e
2266 * and {CROTCHET} is U+1d15f (a crotchet or quarter-note)
2267 * UTF-16: 0xd834 0xdd5f
2268 * UTF-8: 0xf0 0x9d 0x85 0x9f
2269 */
2270 const char text[] = "\0<\0?\0x\0m\0l\0"
2271 " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2272 " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0"
2273 "1\0"
2274 "6\0'"
2275 "\0?\0>\0\n"
2276 "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0["
2277 "\xd8\x34\xdd\x5e\xd8\x34\xdd\x5f"
2278 "\0]\0]\0>\0<\0/\0a\0>";
2279 #ifdef XML_UNICODE
2280 const XML_Char *expected = XCS("\xd834\xdd5e\xd834\xdd5f");
2281 #else
2282 const XML_Char *expected = XCS("\xf0\x9d\x85\x9e\xf0\x9d\x85\x9f");
2283 #endif
2284 CharData storage;
2285
2286 CharData_Init(&storage);
2287 XML_SetUserData(g_parser, &storage);
2288 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2289
2290 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
2291 == XML_STATUS_ERROR)
2292 xml_failure(g_parser);
2293 CharData_CheckXMLChars(&storage, expected);
2294 }
2295 END_TEST
2296
2297 /* Test that an element name with a UTF-16 surrogate pair is rejected */
START_TEST(test_utf16_bad_surrogate_pair)2298 START_TEST(test_utf16_bad_surrogate_pair) {
2299 /* Test data is:
2300 * <?xml version='1.0' encoding='utf-16'?>
2301 * <a><![CDATA[{BADLINB}]]></a>
2302 *
2303 * where {BADLINB} is U+10000 (the first Linear B character)
2304 * with the UTF-16 surrogate pair in the wrong order, i.e.
2305 * 0xdc00 0xd800
2306 */
2307 const char text[] = "\0<\0?\0x\0m\0l\0"
2308 " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2309 " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0"
2310 "1\0"
2311 "6\0'"
2312 "\0?\0>\0\n"
2313 "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0["
2314 "\xdc\x00\xd8\x00"
2315 "\0]\0]\0>\0<\0/\0a\0>";
2316
2317 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
2318 != XML_STATUS_ERROR)
2319 fail("Reversed UTF-16 surrogate pair not faulted");
2320 if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
2321 xml_failure(g_parser);
2322 }
2323 END_TEST
2324
START_TEST(test_bad_cdata)2325 START_TEST(test_bad_cdata) {
2326 struct CaseData {
2327 const char *text;
2328 enum XML_Error expectedError;
2329 };
2330
2331 struct CaseData cases[]
2332 = {{"<a><", XML_ERROR_UNCLOSED_TOKEN},
2333 {"<a><!", XML_ERROR_UNCLOSED_TOKEN},
2334 {"<a><![", XML_ERROR_UNCLOSED_TOKEN},
2335 {"<a><![C", XML_ERROR_UNCLOSED_TOKEN},
2336 {"<a><![CD", XML_ERROR_UNCLOSED_TOKEN},
2337 {"<a><![CDA", XML_ERROR_UNCLOSED_TOKEN},
2338 {"<a><![CDAT", XML_ERROR_UNCLOSED_TOKEN},
2339 {"<a><![CDATA", XML_ERROR_UNCLOSED_TOKEN},
2340
2341 {"<a><![CDATA[", XML_ERROR_UNCLOSED_CDATA_SECTION},
2342 {"<a><![CDATA[]", XML_ERROR_UNCLOSED_CDATA_SECTION},
2343 {"<a><![CDATA[]]", XML_ERROR_UNCLOSED_CDATA_SECTION},
2344
2345 {"<a><!<a/>", XML_ERROR_INVALID_TOKEN},
2346 {"<a><![<a/>", XML_ERROR_UNCLOSED_TOKEN}, /* ?! */
2347 {"<a><![C<a/>", XML_ERROR_UNCLOSED_TOKEN}, /* ?! */
2348 {"<a><![CD<a/>", XML_ERROR_INVALID_TOKEN},
2349 {"<a><![CDA<a/>", XML_ERROR_INVALID_TOKEN},
2350 {"<a><![CDAT<a/>", XML_ERROR_INVALID_TOKEN},
2351 {"<a><![CDATA<a/>", XML_ERROR_INVALID_TOKEN},
2352
2353 {"<a><![CDATA[<a/>", XML_ERROR_UNCLOSED_CDATA_SECTION},
2354 {"<a><![CDATA[]<a/>", XML_ERROR_UNCLOSED_CDATA_SECTION},
2355 {"<a><![CDATA[]]<a/>", XML_ERROR_UNCLOSED_CDATA_SECTION}};
2356
2357 size_t i = 0;
2358 for (; i < sizeof(cases) / sizeof(struct CaseData); i++) {
2359 const enum XML_Status actualStatus = _XML_Parse_SINGLE_BYTES(
2360 g_parser, cases[i].text, (int)strlen(cases[i].text), XML_TRUE);
2361 const enum XML_Error actualError = XML_GetErrorCode(g_parser);
2362
2363 assert(actualStatus == XML_STATUS_ERROR);
2364
2365 if (actualError != cases[i].expectedError) {
2366 char message[100];
2367 sprintf(message,
2368 "Expected error %d but got error %d for case %u: \"%s\"\n",
2369 cases[i].expectedError, actualError, (unsigned int)i + 1,
2370 cases[i].text);
2371 fail(message);
2372 }
2373
2374 XML_ParserReset(g_parser, NULL);
2375 }
2376 }
2377 END_TEST
2378
2379 /* Test failures in UTF-16 CDATA */
START_TEST(test_bad_cdata_utf16)2380 START_TEST(test_bad_cdata_utf16) {
2381 struct CaseData {
2382 size_t text_bytes;
2383 const char *text;
2384 enum XML_Error expected_error;
2385 };
2386
2387 const char prolog[] = "\0<\0?\0x\0m\0l\0"
2388 " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2389 " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0"
2390 "1\0"
2391 "6\0'"
2392 "\0?\0>\0\n"
2393 "\0<\0a\0>";
2394 struct CaseData cases[] = {
2395 {1, "\0", XML_ERROR_UNCLOSED_TOKEN},
2396 {2, "\0<", XML_ERROR_UNCLOSED_TOKEN},
2397 {3, "\0<\0", XML_ERROR_UNCLOSED_TOKEN},
2398 {4, "\0<\0!", XML_ERROR_UNCLOSED_TOKEN},
2399 {5, "\0<\0!\0", XML_ERROR_UNCLOSED_TOKEN},
2400 {6, "\0<\0!\0[", XML_ERROR_UNCLOSED_TOKEN},
2401 {7, "\0<\0!\0[\0", XML_ERROR_UNCLOSED_TOKEN},
2402 {8, "\0<\0!\0[\0C", XML_ERROR_UNCLOSED_TOKEN},
2403 {9, "\0<\0!\0[\0C\0", XML_ERROR_UNCLOSED_TOKEN},
2404 {10, "\0<\0!\0[\0C\0D", XML_ERROR_UNCLOSED_TOKEN},
2405 {11, "\0<\0!\0[\0C\0D\0", XML_ERROR_UNCLOSED_TOKEN},
2406 {12, "\0<\0!\0[\0C\0D\0A", XML_ERROR_UNCLOSED_TOKEN},
2407 {13, "\0<\0!\0[\0C\0D\0A\0", XML_ERROR_UNCLOSED_TOKEN},
2408 {14, "\0<\0!\0[\0C\0D\0A\0T", XML_ERROR_UNCLOSED_TOKEN},
2409 {15, "\0<\0!\0[\0C\0D\0A\0T\0", XML_ERROR_UNCLOSED_TOKEN},
2410 {16, "\0<\0!\0[\0C\0D\0A\0T\0A", XML_ERROR_UNCLOSED_TOKEN},
2411 {17, "\0<\0!\0[\0C\0D\0A\0T\0A\0", XML_ERROR_UNCLOSED_TOKEN},
2412 {18, "\0<\0!\0[\0C\0D\0A\0T\0A\0[", XML_ERROR_UNCLOSED_CDATA_SECTION},
2413 {19, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0", XML_ERROR_UNCLOSED_CDATA_SECTION},
2414 {20, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z", XML_ERROR_UNCLOSED_CDATA_SECTION},
2415 /* Now add a four-byte UTF-16 character */
2416 {21, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8",
2417 XML_ERROR_UNCLOSED_CDATA_SECTION},
2418 {22, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8\x34", XML_ERROR_PARTIAL_CHAR},
2419 {23, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8\x34\xdd",
2420 XML_ERROR_PARTIAL_CHAR},
2421 {24, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8\x34\xdd\x5e",
2422 XML_ERROR_UNCLOSED_CDATA_SECTION}};
2423 size_t i;
2424
2425 for (i = 0; i < sizeof(cases) / sizeof(struct CaseData); i++) {
2426 enum XML_Status actual_status;
2427 enum XML_Error actual_error;
2428
2429 if (_XML_Parse_SINGLE_BYTES(g_parser, prolog, (int)sizeof(prolog) - 1,
2430 XML_FALSE)
2431 == XML_STATUS_ERROR)
2432 xml_failure(g_parser);
2433 actual_status = _XML_Parse_SINGLE_BYTES(g_parser, cases[i].text,
2434 (int)cases[i].text_bytes, XML_TRUE);
2435 assert(actual_status == XML_STATUS_ERROR);
2436 actual_error = XML_GetErrorCode(g_parser);
2437 if (actual_error != cases[i].expected_error) {
2438 char message[1024];
2439
2440 sprintf(message,
2441 "Expected error %d (%" XML_FMT_STR "), got %d (%" XML_FMT_STR
2442 ") for case %lu\n",
2443 cases[i].expected_error, XML_ErrorString(cases[i].expected_error),
2444 actual_error, XML_ErrorString(actual_error),
2445 (long unsigned)(i + 1));
2446 fail(message);
2447 }
2448 XML_ParserReset(g_parser, NULL);
2449 }
2450 }
2451 END_TEST
2452
2453 static const char *long_cdata_text
2454 = "<s><![CDATA["
2455 "012345678901234567890123456789012345678901234567890123456789"
2456 "012345678901234567890123456789012345678901234567890123456789"
2457 "012345678901234567890123456789012345678901234567890123456789"
2458 "012345678901234567890123456789012345678901234567890123456789"
2459 "012345678901234567890123456789012345678901234567890123456789"
2460 "012345678901234567890123456789012345678901234567890123456789"
2461 "012345678901234567890123456789012345678901234567890123456789"
2462 "012345678901234567890123456789012345678901234567890123456789"
2463 "012345678901234567890123456789012345678901234567890123456789"
2464 "012345678901234567890123456789012345678901234567890123456789"
2465 "012345678901234567890123456789012345678901234567890123456789"
2466 "012345678901234567890123456789012345678901234567890123456789"
2467 "012345678901234567890123456789012345678901234567890123456789"
2468 "012345678901234567890123456789012345678901234567890123456789"
2469 "012345678901234567890123456789012345678901234567890123456789"
2470 "012345678901234567890123456789012345678901234567890123456789"
2471 "012345678901234567890123456789012345678901234567890123456789"
2472 "012345678901234567890123456789012345678901234567890123456789"
2473 "012345678901234567890123456789012345678901234567890123456789"
2474 "012345678901234567890123456789012345678901234567890123456789"
2475 "]]></s>";
2476
2477 /* Test stopping the parser in cdata handler */
START_TEST(test_stop_parser_between_cdata_calls)2478 START_TEST(test_stop_parser_between_cdata_calls) {
2479 const char *text = long_cdata_text;
2480
2481 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2482 resumable = XML_FALSE;
2483 expect_failure(text, XML_ERROR_ABORTED, "Parse not aborted in CDATA handler");
2484 }
2485 END_TEST
2486
2487 /* Test suspending the parser in cdata handler */
START_TEST(test_suspend_parser_between_cdata_calls)2488 START_TEST(test_suspend_parser_between_cdata_calls) {
2489 const char *text = long_cdata_text;
2490 enum XML_Status result;
2491
2492 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2493 resumable = XML_TRUE;
2494 result = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE);
2495 if (result != XML_STATUS_SUSPENDED) {
2496 if (result == XML_STATUS_ERROR)
2497 xml_failure(g_parser);
2498 fail("Parse not suspended in CDATA handler");
2499 }
2500 if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE)
2501 xml_failure(g_parser);
2502 }
2503 END_TEST
2504
2505 /* Test memory allocation functions */
START_TEST(test_memory_allocation)2506 START_TEST(test_memory_allocation) {
2507 char *buffer = (char *)XML_MemMalloc(g_parser, 256);
2508 char *p;
2509
2510 if (buffer == NULL) {
2511 fail("Allocation failed");
2512 } else {
2513 /* Try writing to memory; some OSes try to cheat! */
2514 buffer[0] = 'T';
2515 buffer[1] = 'E';
2516 buffer[2] = 'S';
2517 buffer[3] = 'T';
2518 buffer[4] = '\0';
2519 if (strcmp(buffer, "TEST") != 0) {
2520 fail("Memory not writable");
2521 } else {
2522 p = (char *)XML_MemRealloc(g_parser, buffer, 512);
2523 if (p == NULL) {
2524 fail("Reallocation failed");
2525 } else {
2526 /* Write again, just to be sure */
2527 buffer = p;
2528 buffer[0] = 'V';
2529 if (strcmp(buffer, "VEST") != 0) {
2530 fail("Reallocated memory not writable");
2531 }
2532 }
2533 }
2534 XML_MemFree(g_parser, buffer);
2535 }
2536 }
2537 END_TEST
2538
2539 static void XMLCALL
record_default_handler(void * userData,const XML_Char * s,int len)2540 record_default_handler(void *userData, const XML_Char *s, int len) {
2541 UNUSED_P(s);
2542 UNUSED_P(len);
2543 CharData_AppendXMLChars((CharData *)userData, XCS("D"), 1);
2544 }
2545
2546 static void XMLCALL
record_cdata_handler(void * userData,const XML_Char * s,int len)2547 record_cdata_handler(void *userData, const XML_Char *s, int len) {
2548 UNUSED_P(s);
2549 UNUSED_P(len);
2550 CharData_AppendXMLChars((CharData *)userData, XCS("C"), 1);
2551 XML_DefaultCurrent(g_parser);
2552 }
2553
2554 static void XMLCALL
record_cdata_nodefault_handler(void * userData,const XML_Char * s,int len)2555 record_cdata_nodefault_handler(void *userData, const XML_Char *s, int len) {
2556 UNUSED_P(s);
2557 UNUSED_P(len);
2558 CharData_AppendXMLChars((CharData *)userData, XCS("c"), 1);
2559 }
2560
2561 static void XMLCALL
record_skip_handler(void * userData,const XML_Char * entityName,int is_parameter_entity)2562 record_skip_handler(void *userData, const XML_Char *entityName,
2563 int is_parameter_entity) {
2564 UNUSED_P(entityName);
2565 CharData_AppendXMLChars((CharData *)userData,
2566 is_parameter_entity ? XCS("E") : XCS("e"), 1);
2567 }
2568
2569 /* Test XML_DefaultCurrent() passes handling on correctly */
START_TEST(test_default_current)2570 START_TEST(test_default_current) {
2571 const char *text = "<doc>hell]</doc>";
2572 const char *entity_text = "<!DOCTYPE doc [\n"
2573 "<!ENTITY entity '%'>\n"
2574 "]>\n"
2575 "<doc>&entity;</doc>";
2576 CharData storage;
2577
2578 XML_SetDefaultHandler(g_parser, record_default_handler);
2579 XML_SetCharacterDataHandler(g_parser, record_cdata_handler);
2580 CharData_Init(&storage);
2581 XML_SetUserData(g_parser, &storage);
2582 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2583 == XML_STATUS_ERROR)
2584 xml_failure(g_parser);
2585 CharData_CheckXMLChars(&storage, XCS("DCDCDCDCDCDD"));
2586
2587 /* Again, without the defaulting */
2588 XML_ParserReset(g_parser, NULL);
2589 XML_SetDefaultHandler(g_parser, record_default_handler);
2590 XML_SetCharacterDataHandler(g_parser, record_cdata_nodefault_handler);
2591 CharData_Init(&storage);
2592 XML_SetUserData(g_parser, &storage);
2593 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2594 == XML_STATUS_ERROR)
2595 xml_failure(g_parser);
2596 CharData_CheckXMLChars(&storage, XCS("DcccccD"));
2597
2598 /* Now with an internal entity to complicate matters */
2599 XML_ParserReset(g_parser, NULL);
2600 XML_SetDefaultHandler(g_parser, record_default_handler);
2601 XML_SetCharacterDataHandler(g_parser, record_cdata_handler);
2602 CharData_Init(&storage);
2603 XML_SetUserData(g_parser, &storage);
2604 if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text),
2605 XML_TRUE)
2606 == XML_STATUS_ERROR)
2607 xml_failure(g_parser);
2608 /* The default handler suppresses the entity */
2609 CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDDD"));
2610
2611 /* Again, with a skip handler */
2612 XML_ParserReset(g_parser, NULL);
2613 XML_SetDefaultHandler(g_parser, record_default_handler);
2614 XML_SetCharacterDataHandler(g_parser, record_cdata_handler);
2615 XML_SetSkippedEntityHandler(g_parser, record_skip_handler);
2616 CharData_Init(&storage);
2617 XML_SetUserData(g_parser, &storage);
2618 if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text),
2619 XML_TRUE)
2620 == XML_STATUS_ERROR)
2621 xml_failure(g_parser);
2622 /* The default handler suppresses the entity */
2623 CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDeD"));
2624
2625 /* This time, allow the entity through */
2626 XML_ParserReset(g_parser, NULL);
2627 XML_SetDefaultHandlerExpand(g_parser, record_default_handler);
2628 XML_SetCharacterDataHandler(g_parser, record_cdata_handler);
2629 CharData_Init(&storage);
2630 XML_SetUserData(g_parser, &storage);
2631 if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text),
2632 XML_TRUE)
2633 == XML_STATUS_ERROR)
2634 xml_failure(g_parser);
2635 CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDCDD"));
2636
2637 /* Finally, without passing the cdata to the default handler */
2638 XML_ParserReset(g_parser, NULL);
2639 XML_SetDefaultHandlerExpand(g_parser, record_default_handler);
2640 XML_SetCharacterDataHandler(g_parser, record_cdata_nodefault_handler);
2641 CharData_Init(&storage);
2642 XML_SetUserData(g_parser, &storage);
2643 if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text),
2644 XML_TRUE)
2645 == XML_STATUS_ERROR)
2646 xml_failure(g_parser);
2647 CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDcD"));
2648 }
2649 END_TEST
2650
2651 /* Test DTD element parsing code paths */
START_TEST(test_dtd_elements)2652 START_TEST(test_dtd_elements) {
2653 const char *text = "<!DOCTYPE doc [\n"
2654 "<!ELEMENT doc (chapter)>\n"
2655 "<!ELEMENT chapter (#PCDATA)>\n"
2656 "]>\n"
2657 "<doc><chapter>Wombats are go</chapter></doc>";
2658
2659 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
2660 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2661 == XML_STATUS_ERROR)
2662 xml_failure(g_parser);
2663 }
2664 END_TEST
2665
2666 /* Test foreign DTD handling */
START_TEST(test_set_foreign_dtd)2667 START_TEST(test_set_foreign_dtd) {
2668 const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n";
2669 const char *text2 = "<doc>&entity;</doc>";
2670 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
2671
2672 /* Check hash salt is passed through too */
2673 XML_SetHashSalt(g_parser, 0x12345678);
2674 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2675 XML_SetUserData(g_parser, &test_data);
2676 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
2677 /* Add a default handler to exercise more code paths */
2678 XML_SetDefaultHandler(g_parser, dummy_default_handler);
2679 if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE)
2680 fail("Could not set foreign DTD");
2681 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
2682 == XML_STATUS_ERROR)
2683 xml_failure(g_parser);
2684
2685 /* Ensure that trying to set the DTD after parsing has started
2686 * is faulted, even if it's the same setting.
2687 */
2688 if (XML_UseForeignDTD(g_parser, XML_TRUE)
2689 != XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING)
2690 fail("Failed to reject late foreign DTD setting");
2691 /* Ditto for the hash salt */
2692 if (XML_SetHashSalt(g_parser, 0x23456789))
2693 fail("Failed to reject late hash salt change");
2694
2695 /* Now finish the parse */
2696 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
2697 == XML_STATUS_ERROR)
2698 xml_failure(g_parser);
2699 }
2700 END_TEST
2701
2702 /* Test foreign DTD handling with a failing NotStandalone handler */
START_TEST(test_foreign_dtd_not_standalone)2703 START_TEST(test_foreign_dtd_not_standalone) {
2704 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
2705 "<doc>&entity;</doc>";
2706 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
2707
2708 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2709 XML_SetUserData(g_parser, &test_data);
2710 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
2711 XML_SetNotStandaloneHandler(g_parser, reject_not_standalone_handler);
2712 if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE)
2713 fail("Could not set foreign DTD");
2714 expect_failure(text, XML_ERROR_NOT_STANDALONE,
2715 "NotStandalonehandler failed to reject");
2716 }
2717 END_TEST
2718
2719 /* Test invalid character in a foreign DTD is faulted */
START_TEST(test_invalid_foreign_dtd)2720 START_TEST(test_invalid_foreign_dtd) {
2721 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
2722 "<doc>&entity;</doc>";
2723 ExtFaults test_data
2724 = {"$", "Dollar not faulted", NULL, XML_ERROR_INVALID_TOKEN};
2725
2726 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2727 XML_SetUserData(g_parser, &test_data);
2728 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
2729 XML_UseForeignDTD(g_parser, XML_TRUE);
2730 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
2731 "Bad DTD should not have been accepted");
2732 }
2733 END_TEST
2734
2735 /* Test foreign DTD use with a doctype */
START_TEST(test_foreign_dtd_with_doctype)2736 START_TEST(test_foreign_dtd_with_doctype) {
2737 const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n"
2738 "<!DOCTYPE doc [<!ENTITY entity 'hello world'>]>\n";
2739 const char *text2 = "<doc>&entity;</doc>";
2740 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
2741
2742 /* Check hash salt is passed through too */
2743 XML_SetHashSalt(g_parser, 0x12345678);
2744 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2745 XML_SetUserData(g_parser, &test_data);
2746 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
2747 /* Add a default handler to exercise more code paths */
2748 XML_SetDefaultHandler(g_parser, dummy_default_handler);
2749 if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE)
2750 fail("Could not set foreign DTD");
2751 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
2752 == XML_STATUS_ERROR)
2753 xml_failure(g_parser);
2754
2755 /* Ensure that trying to set the DTD after parsing has started
2756 * is faulted, even if it's the same setting.
2757 */
2758 if (XML_UseForeignDTD(g_parser, XML_TRUE)
2759 != XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING)
2760 fail("Failed to reject late foreign DTD setting");
2761 /* Ditto for the hash salt */
2762 if (XML_SetHashSalt(g_parser, 0x23456789))
2763 fail("Failed to reject late hash salt change");
2764
2765 /* Now finish the parse */
2766 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
2767 == XML_STATUS_ERROR)
2768 xml_failure(g_parser);
2769 }
2770 END_TEST
2771
2772 /* Test XML_UseForeignDTD with no external subset present */
2773 static int XMLCALL
external_entity_null_loader(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)2774 external_entity_null_loader(XML_Parser parser, const XML_Char *context,
2775 const XML_Char *base, const XML_Char *systemId,
2776 const XML_Char *publicId) {
2777 UNUSED_P(parser);
2778 UNUSED_P(context);
2779 UNUSED_P(base);
2780 UNUSED_P(systemId);
2781 UNUSED_P(publicId);
2782 return XML_STATUS_OK;
2783 }
2784
START_TEST(test_foreign_dtd_without_external_subset)2785 START_TEST(test_foreign_dtd_without_external_subset) {
2786 const char *text = "<!DOCTYPE doc [<!ENTITY foo 'bar'>]>\n"
2787 "<doc>&foo;</doc>";
2788
2789 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2790 XML_SetUserData(g_parser, NULL);
2791 XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader);
2792 XML_UseForeignDTD(g_parser, XML_TRUE);
2793 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2794 == XML_STATUS_ERROR)
2795 xml_failure(g_parser);
2796 }
2797 END_TEST
2798
START_TEST(test_empty_foreign_dtd)2799 START_TEST(test_empty_foreign_dtd) {
2800 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
2801 "<doc>&entity;</doc>";
2802
2803 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2804 XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader);
2805 XML_UseForeignDTD(g_parser, XML_TRUE);
2806 expect_failure(text, XML_ERROR_UNDEFINED_ENTITY,
2807 "Undefined entity not faulted");
2808 }
2809 END_TEST
2810
2811 /* Test XML Base is set and unset appropriately */
START_TEST(test_set_base)2812 START_TEST(test_set_base) {
2813 const XML_Char *old_base;
2814 const XML_Char *new_base = XCS("/local/file/name.xml");
2815
2816 old_base = XML_GetBase(g_parser);
2817 if (XML_SetBase(g_parser, new_base) != XML_STATUS_OK)
2818 fail("Unable to set base");
2819 if (xcstrcmp(XML_GetBase(g_parser), new_base) != 0)
2820 fail("Base setting not correct");
2821 if (XML_SetBase(g_parser, NULL) != XML_STATUS_OK)
2822 fail("Unable to NULL base");
2823 if (XML_GetBase(g_parser) != NULL)
2824 fail("Base setting not nulled");
2825 XML_SetBase(g_parser, old_base);
2826 }
2827 END_TEST
2828
2829 /* Test attribute counts, indexing, etc */
2830 typedef struct attrInfo {
2831 const XML_Char *name;
2832 const XML_Char *value;
2833 } AttrInfo;
2834
2835 typedef struct elementInfo {
2836 const XML_Char *name;
2837 int attr_count;
2838 const XML_Char *id_name;
2839 AttrInfo *attributes;
2840 } ElementInfo;
2841
2842 static void XMLCALL
counting_start_element_handler(void * userData,const XML_Char * name,const XML_Char ** atts)2843 counting_start_element_handler(void *userData, const XML_Char *name,
2844 const XML_Char **atts) {
2845 ElementInfo *info = (ElementInfo *)userData;
2846 AttrInfo *attr;
2847 int count, id, i;
2848
2849 while (info->name != NULL) {
2850 if (! xcstrcmp(name, info->name))
2851 break;
2852 info++;
2853 }
2854 if (info->name == NULL)
2855 fail("Element not recognised");
2856 /* The attribute count is twice what you might expect. It is a
2857 * count of items in atts, an array which contains alternating
2858 * attribute names and attribute values. For the naive user this
2859 * is possibly a little unexpected, but it is what the
2860 * documentation in expat.h tells us to expect.
2861 */
2862 count = XML_GetSpecifiedAttributeCount(g_parser);
2863 if (info->attr_count * 2 != count) {
2864 fail("Not got expected attribute count");
2865 return;
2866 }
2867 id = XML_GetIdAttributeIndex(g_parser);
2868 if (id == -1 && info->id_name != NULL) {
2869 fail("ID not present");
2870 return;
2871 }
2872 if (id != -1 && xcstrcmp(atts[id], info->id_name)) {
2873 fail("ID does not have the correct name");
2874 return;
2875 }
2876 for (i = 0; i < info->attr_count; i++) {
2877 attr = info->attributes;
2878 while (attr->name != NULL) {
2879 if (! xcstrcmp(atts[0], attr->name))
2880 break;
2881 attr++;
2882 }
2883 if (attr->name == NULL) {
2884 fail("Attribute not recognised");
2885 return;
2886 }
2887 if (xcstrcmp(atts[1], attr->value)) {
2888 fail("Attribute has wrong value");
2889 return;
2890 }
2891 /* Remember, two entries in atts per attribute (see above) */
2892 atts += 2;
2893 }
2894 }
2895
START_TEST(test_attributes)2896 START_TEST(test_attributes) {
2897 const char *text = "<!DOCTYPE doc [\n"
2898 "<!ELEMENT doc (tag)>\n"
2899 "<!ATTLIST doc id ID #REQUIRED>\n"
2900 "]>"
2901 "<doc a='1' id='one' b='2'>"
2902 "<tag c='3'/>"
2903 "</doc>";
2904 AttrInfo doc_info[] = {{XCS("a"), XCS("1")},
2905 {XCS("b"), XCS("2")},
2906 {XCS("id"), XCS("one")},
2907 {NULL, NULL}};
2908 AttrInfo tag_info[] = {{XCS("c"), XCS("3")}, {NULL, NULL}};
2909 ElementInfo info[] = {{XCS("doc"), 3, XCS("id"), NULL},
2910 {XCS("tag"), 1, NULL, NULL},
2911 {NULL, 0, NULL, NULL}};
2912 info[0].attributes = doc_info;
2913 info[1].attributes = tag_info;
2914
2915 XML_SetStartElementHandler(g_parser, counting_start_element_handler);
2916 XML_SetUserData(g_parser, info);
2917 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2918 == XML_STATUS_ERROR)
2919 xml_failure(g_parser);
2920 }
2921 END_TEST
2922
2923 /* Test reset works correctly in the middle of processing an internal
2924 * entity. Exercises some obscure code in XML_ParserReset().
2925 */
START_TEST(test_reset_in_entity)2926 START_TEST(test_reset_in_entity) {
2927 const char *text = "<!DOCTYPE doc [\n"
2928 "<!ENTITY wombat 'wom'>\n"
2929 "<!ENTITY entity 'hi &wom; there'>\n"
2930 "]>\n"
2931 "<doc>&entity;</doc>";
2932 XML_ParsingStatus status;
2933
2934 resumable = XML_TRUE;
2935 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2936 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
2937 == XML_STATUS_ERROR)
2938 xml_failure(g_parser);
2939 XML_GetParsingStatus(g_parser, &status);
2940 if (status.parsing != XML_SUSPENDED)
2941 fail("Parsing status not SUSPENDED");
2942 XML_ParserReset(g_parser, NULL);
2943 XML_GetParsingStatus(g_parser, &status);
2944 if (status.parsing != XML_INITIALIZED)
2945 fail("Parsing status doesn't reset to INITIALIZED");
2946 }
2947 END_TEST
2948
2949 /* Test that resume correctly passes through parse errors */
START_TEST(test_resume_invalid_parse)2950 START_TEST(test_resume_invalid_parse) {
2951 const char *text = "<doc>Hello</doc"; /* Missing closing wedge */
2952
2953 resumable = XML_TRUE;
2954 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2955 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
2956 == XML_STATUS_ERROR)
2957 xml_failure(g_parser);
2958 if (XML_ResumeParser(g_parser) == XML_STATUS_OK)
2959 fail("Resumed invalid parse not faulted");
2960 if (XML_GetErrorCode(g_parser) != XML_ERROR_UNCLOSED_TOKEN)
2961 fail("Invalid parse not correctly faulted");
2962 }
2963 END_TEST
2964
2965 /* Test that re-suspended parses are correctly passed through */
START_TEST(test_resume_resuspended)2966 START_TEST(test_resume_resuspended) {
2967 const char *text = "<doc>Hello<meep/>world</doc>";
2968
2969 resumable = XML_TRUE;
2970 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2971 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
2972 == XML_STATUS_ERROR)
2973 xml_failure(g_parser);
2974 resumable = XML_TRUE;
2975 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2976 if (XML_ResumeParser(g_parser) != XML_STATUS_SUSPENDED)
2977 fail("Resumption not suspended");
2978 /* This one should succeed and finish up */
2979 if (XML_ResumeParser(g_parser) != XML_STATUS_OK)
2980 xml_failure(g_parser);
2981 }
2982 END_TEST
2983
2984 /* Test that CDATA shows up correctly through a default handler */
START_TEST(test_cdata_default)2985 START_TEST(test_cdata_default) {
2986 const char *text = "<doc><![CDATA[Hello\nworld]]></doc>";
2987 const XML_Char *expected = XCS("<doc><![CDATA[Hello\nworld]]></doc>");
2988 CharData storage;
2989
2990 CharData_Init(&storage);
2991 XML_SetUserData(g_parser, &storage);
2992 XML_SetDefaultHandler(g_parser, accumulate_characters);
2993
2994 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2995 == XML_STATUS_ERROR)
2996 xml_failure(g_parser);
2997 CharData_CheckXMLChars(&storage, expected);
2998 }
2999 END_TEST
3000
3001 /* Test resetting a subordinate parser does exactly nothing */
3002 static int XMLCALL
external_entity_resetter(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3003 external_entity_resetter(XML_Parser parser, const XML_Char *context,
3004 const XML_Char *base, const XML_Char *systemId,
3005 const XML_Char *publicId) {
3006 const char *text = "<!ELEMENT doc (#PCDATA)*>";
3007 XML_Parser ext_parser;
3008 XML_ParsingStatus status;
3009
3010 UNUSED_P(base);
3011 UNUSED_P(systemId);
3012 UNUSED_P(publicId);
3013 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3014 if (ext_parser == NULL)
3015 fail("Could not create external entity parser");
3016 XML_GetParsingStatus(ext_parser, &status);
3017 if (status.parsing != XML_INITIALIZED) {
3018 fail("Parsing status is not INITIALIZED");
3019 return XML_STATUS_ERROR;
3020 }
3021 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3022 == XML_STATUS_ERROR) {
3023 xml_failure(parser);
3024 return XML_STATUS_ERROR;
3025 }
3026 XML_GetParsingStatus(ext_parser, &status);
3027 if (status.parsing != XML_FINISHED) {
3028 fail("Parsing status is not FINISHED");
3029 return XML_STATUS_ERROR;
3030 }
3031 /* Check we can't parse here */
3032 if (XML_Parse(ext_parser, text, (int)strlen(text), XML_TRUE)
3033 != XML_STATUS_ERROR)
3034 fail("Parsing when finished not faulted");
3035 if (XML_GetErrorCode(ext_parser) != XML_ERROR_FINISHED)
3036 fail("Parsing when finished faulted with wrong code");
3037 XML_ParserReset(ext_parser, NULL);
3038 XML_GetParsingStatus(ext_parser, &status);
3039 if (status.parsing != XML_FINISHED) {
3040 fail("Parsing status not still FINISHED");
3041 return XML_STATUS_ERROR;
3042 }
3043 XML_ParserFree(ext_parser);
3044 return XML_STATUS_OK;
3045 }
3046
START_TEST(test_subordinate_reset)3047 START_TEST(test_subordinate_reset) {
3048 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
3049 "<!DOCTYPE doc SYSTEM 'foo'>\n"
3050 "<doc>&entity;</doc>";
3051
3052 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3053 XML_SetExternalEntityRefHandler(g_parser, external_entity_resetter);
3054 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3055 == XML_STATUS_ERROR)
3056 xml_failure(g_parser);
3057 }
3058 END_TEST
3059
3060 /* Test suspending a subordinate parser */
3061
3062 static void XMLCALL
entity_suspending_decl_handler(void * userData,const XML_Char * name,XML_Content * model)3063 entity_suspending_decl_handler(void *userData, const XML_Char *name,
3064 XML_Content *model) {
3065 XML_Parser ext_parser = (XML_Parser)userData;
3066
3067 UNUSED_P(name);
3068 if (XML_StopParser(ext_parser, XML_TRUE) != XML_STATUS_ERROR)
3069 fail("Attempting to suspend a subordinate parser not faulted");
3070 if (XML_GetErrorCode(ext_parser) != XML_ERROR_SUSPEND_PE)
3071 fail("Suspending subordinate parser get wrong code");
3072 XML_SetElementDeclHandler(ext_parser, NULL);
3073 XML_FreeContentModel(g_parser, model);
3074 }
3075
3076 static int XMLCALL
external_entity_suspender(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3077 external_entity_suspender(XML_Parser parser, const XML_Char *context,
3078 const XML_Char *base, const XML_Char *systemId,
3079 const XML_Char *publicId) {
3080 const char *text = "<!ELEMENT doc (#PCDATA)*>";
3081 XML_Parser ext_parser;
3082
3083 UNUSED_P(base);
3084 UNUSED_P(systemId);
3085 UNUSED_P(publicId);
3086 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3087 if (ext_parser == NULL)
3088 fail("Could not create external entity parser");
3089 XML_SetElementDeclHandler(ext_parser, entity_suspending_decl_handler);
3090 XML_SetUserData(ext_parser, ext_parser);
3091 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3092 == XML_STATUS_ERROR) {
3093 xml_failure(ext_parser);
3094 return XML_STATUS_ERROR;
3095 }
3096 XML_ParserFree(ext_parser);
3097 return XML_STATUS_OK;
3098 }
3099
START_TEST(test_subordinate_suspend)3100 START_TEST(test_subordinate_suspend) {
3101 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
3102 "<!DOCTYPE doc SYSTEM 'foo'>\n"
3103 "<doc>&entity;</doc>";
3104
3105 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3106 XML_SetExternalEntityRefHandler(g_parser, external_entity_suspender);
3107 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3108 == XML_STATUS_ERROR)
3109 xml_failure(g_parser);
3110 }
3111 END_TEST
3112
3113 /* Test suspending a subordinate parser from an XML declaration */
3114 /* Increases code coverage of the tests */
3115 static void XMLCALL
entity_suspending_xdecl_handler(void * userData,const XML_Char * version,const XML_Char * encoding,int standalone)3116 entity_suspending_xdecl_handler(void *userData, const XML_Char *version,
3117 const XML_Char *encoding, int standalone) {
3118 XML_Parser ext_parser = (XML_Parser)userData;
3119
3120 UNUSED_P(version);
3121 UNUSED_P(encoding);
3122 UNUSED_P(standalone);
3123 XML_StopParser(ext_parser, resumable);
3124 XML_SetXmlDeclHandler(ext_parser, NULL);
3125 }
3126
3127 static int XMLCALL
external_entity_suspend_xmldecl(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3128 external_entity_suspend_xmldecl(XML_Parser parser, const XML_Char *context,
3129 const XML_Char *base, const XML_Char *systemId,
3130 const XML_Char *publicId) {
3131 const char *text = "<?xml version='1.0' encoding='us-ascii'?>";
3132 XML_Parser ext_parser;
3133 XML_ParsingStatus status;
3134 enum XML_Status rc;
3135
3136 UNUSED_P(base);
3137 UNUSED_P(systemId);
3138 UNUSED_P(publicId);
3139 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3140 if (ext_parser == NULL)
3141 fail("Could not create external entity parser");
3142 XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
3143 XML_SetUserData(ext_parser, ext_parser);
3144 rc = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
3145 XML_GetParsingStatus(ext_parser, &status);
3146 if (resumable) {
3147 if (rc == XML_STATUS_ERROR)
3148 xml_failure(ext_parser);
3149 if (status.parsing != XML_SUSPENDED)
3150 fail("Ext Parsing status not SUSPENDED");
3151 } else {
3152 if (rc != XML_STATUS_ERROR)
3153 fail("Ext parsing not aborted");
3154 if (XML_GetErrorCode(ext_parser) != XML_ERROR_ABORTED)
3155 xml_failure(ext_parser);
3156 if (status.parsing != XML_FINISHED)
3157 fail("Ext Parsing status not FINISHED");
3158 }
3159
3160 XML_ParserFree(ext_parser);
3161 return XML_STATUS_OK;
3162 }
3163
START_TEST(test_subordinate_xdecl_suspend)3164 START_TEST(test_subordinate_xdecl_suspend) {
3165 const char *text
3166 = "<!DOCTYPE doc [\n"
3167 " <!ENTITY entity SYSTEM 'http://example.org/dummy.ent'>\n"
3168 "]>\n"
3169 "<doc>&entity;</doc>";
3170
3171 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3172 XML_SetExternalEntityRefHandler(g_parser, external_entity_suspend_xmldecl);
3173 resumable = XML_TRUE;
3174 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3175 == XML_STATUS_ERROR)
3176 xml_failure(g_parser);
3177 }
3178 END_TEST
3179
START_TEST(test_subordinate_xdecl_abort)3180 START_TEST(test_subordinate_xdecl_abort) {
3181 const char *text
3182 = "<!DOCTYPE doc [\n"
3183 " <!ENTITY entity SYSTEM 'http://example.org/dummy.ent'>\n"
3184 "]>\n"
3185 "<doc>&entity;</doc>";
3186
3187 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3188 XML_SetExternalEntityRefHandler(g_parser, external_entity_suspend_xmldecl);
3189 resumable = XML_FALSE;
3190 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3191 == XML_STATUS_ERROR)
3192 xml_failure(g_parser);
3193 }
3194 END_TEST
3195
3196 /* Test external entity fault handling with suspension */
3197 static int XMLCALL
external_entity_suspending_faulter(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3198 external_entity_suspending_faulter(XML_Parser parser, const XML_Char *context,
3199 const XML_Char *base,
3200 const XML_Char *systemId,
3201 const XML_Char *publicId) {
3202 XML_Parser ext_parser;
3203 ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser);
3204 void *buffer;
3205 int parse_len = (int)strlen(fault->parse_text);
3206
3207 UNUSED_P(base);
3208 UNUSED_P(systemId);
3209 UNUSED_P(publicId);
3210 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3211 if (ext_parser == NULL)
3212 fail("Could not create external entity parser");
3213 XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
3214 XML_SetUserData(ext_parser, ext_parser);
3215 resumable = XML_TRUE;
3216 buffer = XML_GetBuffer(ext_parser, parse_len);
3217 if (buffer == NULL)
3218 fail("Could not allocate parse buffer");
3219 assert(buffer != NULL);
3220 memcpy(buffer, fault->parse_text, parse_len);
3221 if (XML_ParseBuffer(ext_parser, parse_len, XML_FALSE) != XML_STATUS_SUSPENDED)
3222 fail("XML declaration did not suspend");
3223 if (XML_ResumeParser(ext_parser) != XML_STATUS_OK)
3224 xml_failure(ext_parser);
3225 if (XML_ParseBuffer(ext_parser, 0, XML_TRUE) != XML_STATUS_ERROR)
3226 fail(fault->fail_text);
3227 if (XML_GetErrorCode(ext_parser) != fault->error)
3228 xml_failure(ext_parser);
3229
3230 XML_ParserFree(ext_parser);
3231 return XML_STATUS_ERROR;
3232 }
3233
START_TEST(test_ext_entity_invalid_suspended_parse)3234 START_TEST(test_ext_entity_invalid_suspended_parse) {
3235 const char *text = "<!DOCTYPE doc [\n"
3236 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
3237 "]>\n"
3238 "<doc>&en;</doc>";
3239 ExtFaults faults[]
3240 = {{"<?xml version='1.0' encoding='us-ascii'?><",
3241 "Incomplete element declaration not faulted", NULL,
3242 XML_ERROR_UNCLOSED_TOKEN},
3243 {/* First two bytes of a three-byte char */
3244 "<?xml version='1.0' encoding='utf-8'?>\xe2\x82",
3245 "Incomplete character not faulted", NULL, XML_ERROR_PARTIAL_CHAR},
3246 {NULL, NULL, NULL, XML_ERROR_NONE}};
3247 ExtFaults *fault;
3248
3249 for (fault = &faults[0]; fault->parse_text != NULL; fault++) {
3250 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3251 XML_SetExternalEntityRefHandler(g_parser,
3252 external_entity_suspending_faulter);
3253 XML_SetUserData(g_parser, fault);
3254 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
3255 "Parser did not report external entity error");
3256 XML_ParserReset(g_parser, NULL);
3257 }
3258 }
3259 END_TEST
3260
3261 /* Test setting an explicit encoding */
START_TEST(test_explicit_encoding)3262 START_TEST(test_explicit_encoding) {
3263 const char *text1 = "<doc>Hello ";
3264 const char *text2 = " World</doc>";
3265
3266 /* Just check that we can set the encoding to NULL before starting */
3267 if (XML_SetEncoding(g_parser, NULL) != XML_STATUS_OK)
3268 fail("Failed to initialise encoding to NULL");
3269 /* Say we are UTF-8 */
3270 if (XML_SetEncoding(g_parser, XCS("utf-8")) != XML_STATUS_OK)
3271 fail("Failed to set explicit encoding");
3272 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
3273 == XML_STATUS_ERROR)
3274 xml_failure(g_parser);
3275 /* Try to switch encodings mid-parse */
3276 if (XML_SetEncoding(g_parser, XCS("us-ascii")) != XML_STATUS_ERROR)
3277 fail("Allowed encoding change");
3278 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
3279 == XML_STATUS_ERROR)
3280 xml_failure(g_parser);
3281 /* Try now the parse is over */
3282 if (XML_SetEncoding(g_parser, NULL) != XML_STATUS_OK)
3283 fail("Failed to unset encoding");
3284 }
3285 END_TEST
3286
3287 /* Test handling of trailing CR (rather than newline) */
3288 static void XMLCALL
cr_cdata_handler(void * userData,const XML_Char * s,int len)3289 cr_cdata_handler(void *userData, const XML_Char *s, int len) {
3290 int *pfound = (int *)userData;
3291
3292 /* Internal processing turns the CR into a newline for the
3293 * character data handler, but not for the default handler
3294 */
3295 if (len == 1 && (*s == XCS('\n') || *s == XCS('\r')))
3296 *pfound = 1;
3297 }
3298
START_TEST(test_trailing_cr)3299 START_TEST(test_trailing_cr) {
3300 const char *text = "<doc>\r";
3301 int found_cr;
3302
3303 /* Try with a character handler, for code coverage */
3304 XML_SetCharacterDataHandler(g_parser, cr_cdata_handler);
3305 XML_SetUserData(g_parser, &found_cr);
3306 found_cr = 0;
3307 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3308 == XML_STATUS_OK)
3309 fail("Failed to fault unclosed doc");
3310 if (found_cr == 0)
3311 fail("Did not catch the carriage return");
3312 XML_ParserReset(g_parser, NULL);
3313
3314 /* Now with a default handler instead */
3315 XML_SetDefaultHandler(g_parser, cr_cdata_handler);
3316 XML_SetUserData(g_parser, &found_cr);
3317 found_cr = 0;
3318 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3319 == XML_STATUS_OK)
3320 fail("Failed to fault unclosed doc");
3321 if (found_cr == 0)
3322 fail("Did not catch default carriage return");
3323 }
3324 END_TEST
3325
3326 /* Test trailing CR in an external entity parse */
3327 static int XMLCALL
external_entity_cr_catcher(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3328 external_entity_cr_catcher(XML_Parser parser, const XML_Char *context,
3329 const XML_Char *base, const XML_Char *systemId,
3330 const XML_Char *publicId) {
3331 const char *text = "\r";
3332 XML_Parser ext_parser;
3333
3334 UNUSED_P(base);
3335 UNUSED_P(systemId);
3336 UNUSED_P(publicId);
3337 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3338 if (ext_parser == NULL)
3339 fail("Could not create external entity parser");
3340 XML_SetCharacterDataHandler(ext_parser, cr_cdata_handler);
3341 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3342 == XML_STATUS_ERROR)
3343 xml_failure(ext_parser);
3344 XML_ParserFree(ext_parser);
3345 return XML_STATUS_OK;
3346 }
3347
3348 static int XMLCALL
external_entity_bad_cr_catcher(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3349 external_entity_bad_cr_catcher(XML_Parser parser, const XML_Char *context,
3350 const XML_Char *base, const XML_Char *systemId,
3351 const XML_Char *publicId) {
3352 const char *text = "<tag>\r";
3353 XML_Parser ext_parser;
3354
3355 UNUSED_P(base);
3356 UNUSED_P(systemId);
3357 UNUSED_P(publicId);
3358 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3359 if (ext_parser == NULL)
3360 fail("Could not create external entity parser");
3361 XML_SetCharacterDataHandler(ext_parser, cr_cdata_handler);
3362 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3363 == XML_STATUS_OK)
3364 fail("Async entity error not caught");
3365 if (XML_GetErrorCode(ext_parser) != XML_ERROR_ASYNC_ENTITY)
3366 xml_failure(ext_parser);
3367 XML_ParserFree(ext_parser);
3368 return XML_STATUS_OK;
3369 }
3370
START_TEST(test_ext_entity_trailing_cr)3371 START_TEST(test_ext_entity_trailing_cr) {
3372 const char *text = "<!DOCTYPE doc [\n"
3373 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
3374 "]>\n"
3375 "<doc>&en;</doc>";
3376 int found_cr;
3377
3378 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3379 XML_SetExternalEntityRefHandler(g_parser, external_entity_cr_catcher);
3380 XML_SetUserData(g_parser, &found_cr);
3381 found_cr = 0;
3382 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3383 != XML_STATUS_OK)
3384 xml_failure(g_parser);
3385 if (found_cr == 0)
3386 fail("No carriage return found");
3387 XML_ParserReset(g_parser, NULL);
3388
3389 /* Try again with a different trailing CR */
3390 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3391 XML_SetExternalEntityRefHandler(g_parser, external_entity_bad_cr_catcher);
3392 XML_SetUserData(g_parser, &found_cr);
3393 found_cr = 0;
3394 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3395 != XML_STATUS_OK)
3396 xml_failure(g_parser);
3397 if (found_cr == 0)
3398 fail("No carriage return found");
3399 }
3400 END_TEST
3401
3402 /* Test handling of trailing square bracket */
3403 static void XMLCALL
rsqb_handler(void * userData,const XML_Char * s,int len)3404 rsqb_handler(void *userData, const XML_Char *s, int len) {
3405 int *pfound = (int *)userData;
3406
3407 if (len == 1 && *s == XCS(']'))
3408 *pfound = 1;
3409 }
3410
START_TEST(test_trailing_rsqb)3411 START_TEST(test_trailing_rsqb) {
3412 const char *text8 = "<doc>]";
3413 const char text16[] = "\xFF\xFE<\000d\000o\000c\000>\000]\000";
3414 int found_rsqb;
3415 int text8_len = (int)strlen(text8);
3416
3417 XML_SetCharacterDataHandler(g_parser, rsqb_handler);
3418 XML_SetUserData(g_parser, &found_rsqb);
3419 found_rsqb = 0;
3420 if (_XML_Parse_SINGLE_BYTES(g_parser, text8, text8_len, XML_TRUE)
3421 == XML_STATUS_OK)
3422 fail("Failed to fault unclosed doc");
3423 if (found_rsqb == 0)
3424 fail("Did not catch the right square bracket");
3425
3426 /* Try again with a different encoding */
3427 XML_ParserReset(g_parser, NULL);
3428 XML_SetCharacterDataHandler(g_parser, rsqb_handler);
3429 XML_SetUserData(g_parser, &found_rsqb);
3430 found_rsqb = 0;
3431 if (_XML_Parse_SINGLE_BYTES(g_parser, text16, (int)sizeof(text16) - 1,
3432 XML_TRUE)
3433 == XML_STATUS_OK)
3434 fail("Failed to fault unclosed doc");
3435 if (found_rsqb == 0)
3436 fail("Did not catch the right square bracket");
3437
3438 /* And finally with a default handler */
3439 XML_ParserReset(g_parser, NULL);
3440 XML_SetDefaultHandler(g_parser, rsqb_handler);
3441 XML_SetUserData(g_parser, &found_rsqb);
3442 found_rsqb = 0;
3443 if (_XML_Parse_SINGLE_BYTES(g_parser, text16, (int)sizeof(text16) - 1,
3444 XML_TRUE)
3445 == XML_STATUS_OK)
3446 fail("Failed to fault unclosed doc");
3447 if (found_rsqb == 0)
3448 fail("Did not catch the right square bracket");
3449 }
3450 END_TEST
3451
3452 /* Test trailing right square bracket in an external entity parse */
3453 static int XMLCALL
external_entity_rsqb_catcher(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3454 external_entity_rsqb_catcher(XML_Parser parser, const XML_Char *context,
3455 const XML_Char *base, const XML_Char *systemId,
3456 const XML_Char *publicId) {
3457 const char *text = "<tag>]";
3458 XML_Parser ext_parser;
3459
3460 UNUSED_P(base);
3461 UNUSED_P(systemId);
3462 UNUSED_P(publicId);
3463 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3464 if (ext_parser == NULL)
3465 fail("Could not create external entity parser");
3466 XML_SetCharacterDataHandler(ext_parser, rsqb_handler);
3467 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3468 != XML_STATUS_ERROR)
3469 fail("Async entity error not caught");
3470 if (XML_GetErrorCode(ext_parser) != XML_ERROR_ASYNC_ENTITY)
3471 xml_failure(ext_parser);
3472 XML_ParserFree(ext_parser);
3473 return XML_STATUS_OK;
3474 }
3475
START_TEST(test_ext_entity_trailing_rsqb)3476 START_TEST(test_ext_entity_trailing_rsqb) {
3477 const char *text = "<!DOCTYPE doc [\n"
3478 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
3479 "]>\n"
3480 "<doc>&en;</doc>";
3481 int found_rsqb;
3482
3483 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3484 XML_SetExternalEntityRefHandler(g_parser, external_entity_rsqb_catcher);
3485 XML_SetUserData(g_parser, &found_rsqb);
3486 found_rsqb = 0;
3487 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3488 != XML_STATUS_OK)
3489 xml_failure(g_parser);
3490 if (found_rsqb == 0)
3491 fail("No right square bracket found");
3492 }
3493 END_TEST
3494
3495 /* Test CDATA handling in an external entity */
3496 static int XMLCALL
external_entity_good_cdata_ascii(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3497 external_entity_good_cdata_ascii(XML_Parser parser, const XML_Char *context,
3498 const XML_Char *base, const XML_Char *systemId,
3499 const XML_Char *publicId) {
3500 const char *text = "<a><![CDATA[<greeting>Hello, world!</greeting>]]></a>";
3501 const XML_Char *expected = XCS("<greeting>Hello, world!</greeting>");
3502 CharData storage;
3503 XML_Parser ext_parser;
3504
3505 UNUSED_P(base);
3506 UNUSED_P(systemId);
3507 UNUSED_P(publicId);
3508 CharData_Init(&storage);
3509 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3510 if (ext_parser == NULL)
3511 fail("Could not create external entity parser");
3512 XML_SetUserData(ext_parser, &storage);
3513 XML_SetCharacterDataHandler(ext_parser, accumulate_characters);
3514
3515 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3516 == XML_STATUS_ERROR)
3517 xml_failure(ext_parser);
3518 CharData_CheckXMLChars(&storage, expected);
3519
3520 XML_ParserFree(ext_parser);
3521 return XML_STATUS_OK;
3522 }
3523
START_TEST(test_ext_entity_good_cdata)3524 START_TEST(test_ext_entity_good_cdata) {
3525 const char *text = "<!DOCTYPE doc [\n"
3526 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
3527 "]>\n"
3528 "<doc>&en;</doc>";
3529
3530 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3531 XML_SetExternalEntityRefHandler(g_parser, external_entity_good_cdata_ascii);
3532 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3533 != XML_STATUS_OK)
3534 xml_failure(g_parser);
3535 }
3536 END_TEST
3537
3538 /* Test user parameter settings */
3539 /* Variable holding the expected handler userData */
3540 static void *handler_data = NULL;
3541 /* Count of the number of times the comment handler has been invoked */
3542 static int comment_count = 0;
3543 /* Count of the number of skipped entities */
3544 static int skip_count = 0;
3545 /* Count of the number of times the XML declaration handler is invoked */
3546 static int xdecl_count = 0;
3547
3548 static void XMLCALL
xml_decl_handler(void * userData,const XML_Char * version,const XML_Char * encoding,int standalone)3549 xml_decl_handler(void *userData, const XML_Char *version,
3550 const XML_Char *encoding, int standalone) {
3551 UNUSED_P(version);
3552 UNUSED_P(encoding);
3553 if (userData != handler_data)
3554 fail("User data (xml decl) not correctly set");
3555 if (standalone != -1)
3556 fail("Standalone not flagged as not present in XML decl");
3557 xdecl_count++;
3558 }
3559
3560 static void XMLCALL
param_check_skip_handler(void * userData,const XML_Char * entityName,int is_parameter_entity)3561 param_check_skip_handler(void *userData, const XML_Char *entityName,
3562 int is_parameter_entity) {
3563 UNUSED_P(entityName);
3564 UNUSED_P(is_parameter_entity);
3565 if (userData != handler_data)
3566 fail("User data (skip) not correctly set");
3567 skip_count++;
3568 }
3569
3570 static void XMLCALL
data_check_comment_handler(void * userData,const XML_Char * data)3571 data_check_comment_handler(void *userData, const XML_Char *data) {
3572 UNUSED_P(data);
3573 /* Check that the userData passed through is what we expect */
3574 if (userData != handler_data)
3575 fail("User data (parser) not correctly set");
3576 /* Check that the user data in the parser is appropriate */
3577 if (XML_GetUserData(userData) != (void *)1)
3578 fail("User data in parser not correctly set");
3579 comment_count++;
3580 }
3581
3582 static int XMLCALL
external_entity_param_checker(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3583 external_entity_param_checker(XML_Parser parser, const XML_Char *context,
3584 const XML_Char *base, const XML_Char *systemId,
3585 const XML_Char *publicId) {
3586 const char *text = "<!-- Subordinate parser -->\n"
3587 "<!ELEMENT doc (#PCDATA)*>";
3588 XML_Parser ext_parser;
3589
3590 UNUSED_P(base);
3591 UNUSED_P(systemId);
3592 UNUSED_P(publicId);
3593 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3594 if (ext_parser == NULL)
3595 fail("Could not create external entity parser");
3596 handler_data = ext_parser;
3597 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3598 == XML_STATUS_ERROR) {
3599 xml_failure(parser);
3600 return XML_STATUS_ERROR;
3601 }
3602 handler_data = parser;
3603 XML_ParserFree(ext_parser);
3604 return XML_STATUS_OK;
3605 }
3606
START_TEST(test_user_parameters)3607 START_TEST(test_user_parameters) {
3608 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
3609 "<!-- Primary parse -->\n"
3610 "<!DOCTYPE doc SYSTEM 'foo'>\n"
3611 "<doc>&entity;";
3612 const char *epilog = "<!-- Back to primary parser -->\n"
3613 "</doc>";
3614
3615 comment_count = 0;
3616 skip_count = 0;
3617 xdecl_count = 0;
3618 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3619 XML_SetXmlDeclHandler(g_parser, xml_decl_handler);
3620 XML_SetExternalEntityRefHandler(g_parser, external_entity_param_checker);
3621 XML_SetCommentHandler(g_parser, data_check_comment_handler);
3622 XML_SetSkippedEntityHandler(g_parser, param_check_skip_handler);
3623 XML_UseParserAsHandlerArg(g_parser);
3624 XML_SetUserData(g_parser, (void *)1);
3625 handler_data = g_parser;
3626 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
3627 == XML_STATUS_ERROR)
3628 xml_failure(g_parser);
3629 if (comment_count != 2)
3630 fail("Comment handler not invoked enough times");
3631 /* Ensure we can't change policy mid-parse */
3632 if (XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_NEVER))
3633 fail("Changed param entity parsing policy while parsing");
3634 if (_XML_Parse_SINGLE_BYTES(g_parser, epilog, (int)strlen(epilog), XML_TRUE)
3635 == XML_STATUS_ERROR)
3636 xml_failure(g_parser);
3637 if (comment_count != 3)
3638 fail("Comment handler not invoked enough times");
3639 if (skip_count != 1)
3640 fail("Skip handler not invoked enough times");
3641 if (xdecl_count != 1)
3642 fail("XML declaration handler not invoked");
3643 }
3644 END_TEST
3645
3646 /* Test that an explicit external entity handler argument replaces
3647 * the parser as the first argument.
3648 *
3649 * We do not call the first parameter to the external entity handler
3650 * 'parser' for once, since the first time the handler is called it
3651 * will actually be a text string. We need to be able to access the
3652 * global 'parser' variable to create our external entity parser from,
3653 * since there are code paths we need to ensure get executed.
3654 */
3655 static int XMLCALL
external_entity_ref_param_checker(XML_Parser parameter,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3656 external_entity_ref_param_checker(XML_Parser parameter, const XML_Char *context,
3657 const XML_Char *base,
3658 const XML_Char *systemId,
3659 const XML_Char *publicId) {
3660 const char *text = "<!ELEMENT doc (#PCDATA)*>";
3661 XML_Parser ext_parser;
3662
3663 UNUSED_P(base);
3664 UNUSED_P(systemId);
3665 UNUSED_P(publicId);
3666 if ((void *)parameter != handler_data)
3667 fail("External entity ref handler parameter not correct");
3668
3669 /* Here we use the global 'parser' variable */
3670 ext_parser = XML_ExternalEntityParserCreate(g_parser, context, NULL);
3671 if (ext_parser == NULL)
3672 fail("Could not create external entity parser");
3673 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3674 == XML_STATUS_ERROR)
3675 xml_failure(ext_parser);
3676
3677 XML_ParserFree(ext_parser);
3678 return XML_STATUS_OK;
3679 }
3680
START_TEST(test_ext_entity_ref_parameter)3681 START_TEST(test_ext_entity_ref_parameter) {
3682 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
3683 "<!DOCTYPE doc SYSTEM 'foo'>\n"
3684 "<doc>&entity;</doc>";
3685
3686 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3687 XML_SetExternalEntityRefHandler(g_parser, external_entity_ref_param_checker);
3688 /* Set a handler arg that is not NULL and not parser (which is
3689 * what NULL would cause to be passed.
3690 */
3691 XML_SetExternalEntityRefHandlerArg(g_parser, (void *)text);
3692 handler_data = (void *)text;
3693 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3694 == XML_STATUS_ERROR)
3695 xml_failure(g_parser);
3696
3697 /* Now try again with unset args */
3698 XML_ParserReset(g_parser, NULL);
3699 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3700 XML_SetExternalEntityRefHandler(g_parser, external_entity_ref_param_checker);
3701 XML_SetExternalEntityRefHandlerArg(g_parser, NULL);
3702 handler_data = (void *)g_parser;
3703 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3704 == XML_STATUS_ERROR)
3705 xml_failure(g_parser);
3706 }
3707 END_TEST
3708
3709 /* Test the parsing of an empty string */
START_TEST(test_empty_parse)3710 START_TEST(test_empty_parse) {
3711 const char *text = "<doc></doc>";
3712 const char *partial = "<doc>";
3713
3714 if (XML_Parse(g_parser, NULL, 0, XML_FALSE) == XML_STATUS_ERROR)
3715 fail("Parsing empty string faulted");
3716 if (XML_Parse(g_parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR)
3717 fail("Parsing final empty string not faulted");
3718 if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_ELEMENTS)
3719 fail("Parsing final empty string faulted for wrong reason");
3720
3721 /* Now try with valid text before the empty end */
3722 XML_ParserReset(g_parser, NULL);
3723 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
3724 == XML_STATUS_ERROR)
3725 xml_failure(g_parser);
3726 if (XML_Parse(g_parser, NULL, 0, XML_TRUE) == XML_STATUS_ERROR)
3727 fail("Parsing final empty string faulted");
3728
3729 /* Now try with invalid text before the empty end */
3730 XML_ParserReset(g_parser, NULL);
3731 if (_XML_Parse_SINGLE_BYTES(g_parser, partial, (int)strlen(partial),
3732 XML_FALSE)
3733 == XML_STATUS_ERROR)
3734 xml_failure(g_parser);
3735 if (XML_Parse(g_parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR)
3736 fail("Parsing final incomplete empty string not faulted");
3737 }
3738 END_TEST
3739
3740 /* Test XML_Parse for len < 0 */
START_TEST(test_negative_len_parse)3741 START_TEST(test_negative_len_parse) {
3742 const char *const doc = "<root/>";
3743 for (int isFinal = 0; isFinal < 2; isFinal++) {
3744 set_subtest("isFinal=%d", isFinal);
3745
3746 XML_Parser parser = XML_ParserCreate(NULL);
3747
3748 if (XML_GetErrorCode(parser) != XML_ERROR_NONE)
3749 fail("There was not supposed to be any initial parse error.");
3750
3751 const enum XML_Status status = XML_Parse(parser, doc, -1, isFinal);
3752
3753 if (status != XML_STATUS_ERROR)
3754 fail("Negative len was expected to fail the parse but did not.");
3755
3756 if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_ARGUMENT)
3757 fail("Parse error does not match XML_ERROR_INVALID_ARGUMENT.");
3758
3759 XML_ParserFree(parser);
3760 }
3761 }
3762 END_TEST
3763
3764 /* Test XML_ParseBuffer for len < 0 */
START_TEST(test_negative_len_parse_buffer)3765 START_TEST(test_negative_len_parse_buffer) {
3766 const char *const doc = "<root/>";
3767 for (int isFinal = 0; isFinal < 2; isFinal++) {
3768 set_subtest("isFinal=%d", isFinal);
3769
3770 XML_Parser parser = XML_ParserCreate(NULL);
3771
3772 if (XML_GetErrorCode(parser) != XML_ERROR_NONE)
3773 fail("There was not supposed to be any initial parse error.");
3774
3775 void *const buffer = XML_GetBuffer(parser, (int)strlen(doc));
3776
3777 if (buffer == NULL)
3778 fail("XML_GetBuffer failed.");
3779
3780 memcpy(buffer, doc, strlen(doc));
3781
3782 const enum XML_Status status = XML_ParseBuffer(parser, -1, isFinal);
3783
3784 if (status != XML_STATUS_ERROR)
3785 fail("Negative len was expected to fail the parse but did not.");
3786
3787 if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_ARGUMENT)
3788 fail("Parse error does not match XML_ERROR_INVALID_ARGUMENT.");
3789
3790 XML_ParserFree(parser);
3791 }
3792 }
3793 END_TEST
3794
3795 /* Test odd corners of the XML_GetBuffer interface */
3796 static enum XML_Status
get_feature(enum XML_FeatureEnum feature_id,long * presult)3797 get_feature(enum XML_FeatureEnum feature_id, long *presult) {
3798 const XML_Feature *feature = XML_GetFeatureList();
3799
3800 if (feature == NULL)
3801 return XML_STATUS_ERROR;
3802 for (; feature->feature != XML_FEATURE_END; feature++) {
3803 if (feature->feature == feature_id) {
3804 *presult = feature->value;
3805 return XML_STATUS_OK;
3806 }
3807 }
3808 return XML_STATUS_ERROR;
3809 }
3810
3811 /* Having an element name longer than 1024 characters exercises some
3812 * of the pool allocation code in the parser that otherwise does not
3813 * get executed. The count at the end of the line is the number of
3814 * characters (bytes) in the element name by that point.x
3815 */
3816 static const char *get_buffer_test_text
3817 = "<documentwitharidiculouslylongelementnametotease" /* 0x030 */
3818 "aparticularcorneroftheallocationinXML_GetBuffers" /* 0x060 */
3819 "othatwecanimprovethecoverageyetagain012345678901" /* 0x090 */
3820 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x0c0 */
3821 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x0f0 */
3822 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x120 */
3823 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x150 */
3824 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x180 */
3825 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x1b0 */
3826 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x1e0 */
3827 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x210 */
3828 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x240 */
3829 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x270 */
3830 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x2a0 */
3831 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x2d0 */
3832 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x300 */
3833 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x330 */
3834 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x360 */
3835 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x390 */
3836 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x3c0 */
3837 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x3f0 */
3838 "123456789abcdef0123456789abcdef0123456789>\n<ef0"; /* 0x420 */
3839
3840 /* Test odd corners of the XML_GetBuffer interface */
START_TEST(test_get_buffer_1)3841 START_TEST(test_get_buffer_1) {
3842 const char *text = get_buffer_test_text;
3843 void *buffer;
3844 long context_bytes;
3845
3846 /* Attempt to allocate a negative length buffer */
3847 if (XML_GetBuffer(g_parser, -12) != NULL)
3848 fail("Negative length buffer not failed");
3849
3850 /* Now get a small buffer and extend it past valid length */
3851 buffer = XML_GetBuffer(g_parser, 1536);
3852 if (buffer == NULL)
3853 fail("1.5K buffer failed");
3854 assert(buffer != NULL);
3855 memcpy(buffer, text, strlen(text));
3856 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE)
3857 == XML_STATUS_ERROR)
3858 xml_failure(g_parser);
3859 if (XML_GetBuffer(g_parser, INT_MAX) != NULL)
3860 fail("INT_MAX buffer not failed");
3861
3862 /* Now try extending it a more reasonable but still too large
3863 * amount. The allocator in XML_GetBuffer() doubles the buffer
3864 * size until it exceeds the requested amount or INT_MAX. If it
3865 * exceeds INT_MAX, it rejects the request, so we want a request
3866 * between INT_MAX and INT_MAX/2. A gap of 1K seems comfortable,
3867 * with an extra byte just to ensure that the request is off any
3868 * boundary. The request will be inflated internally by
3869 * XML_CONTEXT_BYTES (if defined), so we subtract that from our
3870 * request.
3871 */
3872 if (get_feature(XML_FEATURE_CONTEXT_BYTES, &context_bytes) != XML_STATUS_OK)
3873 context_bytes = 0;
3874 if (XML_GetBuffer(g_parser, INT_MAX - (context_bytes + 1025)) != NULL)
3875 fail("INT_MAX- buffer not failed");
3876
3877 /* Now try extending it a carefully crafted amount */
3878 if (XML_GetBuffer(g_parser, 1000) == NULL)
3879 fail("1000 buffer failed");
3880 }
3881 END_TEST
3882
3883 /* Test more corners of the XML_GetBuffer interface */
START_TEST(test_get_buffer_2)3884 START_TEST(test_get_buffer_2) {
3885 const char *text = get_buffer_test_text;
3886 void *buffer;
3887
3888 /* Now get a decent buffer */
3889 buffer = XML_GetBuffer(g_parser, 1536);
3890 if (buffer == NULL)
3891 fail("1.5K buffer failed");
3892 assert(buffer != NULL);
3893 memcpy(buffer, text, strlen(text));
3894 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE)
3895 == XML_STATUS_ERROR)
3896 xml_failure(g_parser);
3897
3898 /* Extend it, to catch a different code path */
3899 if (XML_GetBuffer(g_parser, 1024) == NULL)
3900 fail("1024 buffer failed");
3901 }
3902 END_TEST
3903
3904 /* Test position information macros */
START_TEST(test_byte_info_at_end)3905 START_TEST(test_byte_info_at_end) {
3906 const char *text = "<doc></doc>";
3907
3908 if (XML_GetCurrentByteIndex(g_parser) != -1
3909 || XML_GetCurrentByteCount(g_parser) != 0)
3910 fail("Byte index/count incorrect at start of parse");
3911 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3912 == XML_STATUS_ERROR)
3913 xml_failure(g_parser);
3914 /* At end, the count will be zero and the index the end of string */
3915 if (XML_GetCurrentByteCount(g_parser) != 0)
3916 fail("Terminal byte count incorrect");
3917 if (XML_GetCurrentByteIndex(g_parser) != (XML_Index)strlen(text))
3918 fail("Terminal byte index incorrect");
3919 }
3920 END_TEST
3921
3922 /* Test position information from errors */
3923 #define PRE_ERROR_STR "<doc></"
3924 #define POST_ERROR_STR "wombat></doc>"
START_TEST(test_byte_info_at_error)3925 START_TEST(test_byte_info_at_error) {
3926 const char *text = PRE_ERROR_STR POST_ERROR_STR;
3927
3928 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3929 == XML_STATUS_OK)
3930 fail("Syntax error not faulted");
3931 if (XML_GetCurrentByteCount(g_parser) != 0)
3932 fail("Error byte count incorrect");
3933 if (XML_GetCurrentByteIndex(g_parser) != strlen(PRE_ERROR_STR))
3934 fail("Error byte index incorrect");
3935 }
3936 END_TEST
3937 #undef PRE_ERROR_STR
3938 #undef POST_ERROR_STR
3939
3940 /* Test position information in handler */
3941 typedef struct ByteTestData {
3942 int start_element_len;
3943 int cdata_len;
3944 int total_string_len;
3945 } ByteTestData;
3946
3947 static void
byte_character_handler(void * userData,const XML_Char * s,int len)3948 byte_character_handler(void *userData, const XML_Char *s, int len) {
3949 #ifdef XML_CONTEXT_BYTES
3950 int offset, size;
3951 const char *buffer;
3952 ByteTestData *data = (ByteTestData *)userData;
3953
3954 UNUSED_P(s);
3955 buffer = XML_GetInputContext(g_parser, &offset, &size);
3956 if (buffer == NULL)
3957 fail("Failed to get context buffer");
3958 if (offset != data->start_element_len)
3959 fail("Context offset in unexpected position");
3960 if (len != data->cdata_len)
3961 fail("CDATA length reported incorrectly");
3962 if (size != data->total_string_len)
3963 fail("Context size is not full buffer");
3964 if (XML_GetCurrentByteIndex(g_parser) != offset)
3965 fail("Character byte index incorrect");
3966 if (XML_GetCurrentByteCount(g_parser) != len)
3967 fail("Character byte count incorrect");
3968 #else
3969 UNUSED_P(s);
3970 UNUSED_P(userData);
3971 UNUSED_P(len);
3972 #endif
3973 }
3974
3975 #define START_ELEMENT "<e>"
3976 #define CDATA_TEXT "Hello"
3977 #define END_ELEMENT "</e>"
START_TEST(test_byte_info_at_cdata)3978 START_TEST(test_byte_info_at_cdata) {
3979 const char *text = START_ELEMENT CDATA_TEXT END_ELEMENT;
3980 int offset, size;
3981 ByteTestData data;
3982
3983 /* Check initial context is empty */
3984 if (XML_GetInputContext(g_parser, &offset, &size) != NULL)
3985 fail("Unexpected context at start of parse");
3986
3987 data.start_element_len = (int)strlen(START_ELEMENT);
3988 data.cdata_len = (int)strlen(CDATA_TEXT);
3989 data.total_string_len = (int)strlen(text);
3990 XML_SetCharacterDataHandler(g_parser, byte_character_handler);
3991 XML_SetUserData(g_parser, &data);
3992 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_OK)
3993 xml_failure(g_parser);
3994 }
3995 END_TEST
3996 #undef START_ELEMENT
3997 #undef CDATA_TEXT
3998 #undef END_ELEMENT
3999
4000 /* Test predefined entities are correctly recognised */
START_TEST(test_predefined_entities)4001 START_TEST(test_predefined_entities) {
4002 const char *text = "<doc><>&"'</doc>";
4003 const XML_Char *expected = XCS("<doc><>&"'</doc>");
4004 const XML_Char *result = XCS("<>&\"'");
4005 CharData storage;
4006
4007 XML_SetDefaultHandler(g_parser, accumulate_characters);
4008 /* run_character_check uses XML_SetCharacterDataHandler(), which
4009 * unfortunately heads off a code path that we need to exercise.
4010 */
4011 CharData_Init(&storage);
4012 XML_SetUserData(g_parser, &storage);
4013 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4014 == XML_STATUS_ERROR)
4015 xml_failure(g_parser);
4016 /* The default handler doesn't translate the entities */
4017 CharData_CheckXMLChars(&storage, expected);
4018
4019 /* Now try again and check the translation */
4020 XML_ParserReset(g_parser, NULL);
4021 run_character_check(text, result);
4022 }
4023 END_TEST
4024
4025 /* Regression test that an invalid tag in an external parameter
4026 * reference in an external DTD is correctly faulted.
4027 *
4028 * Only a few specific tags are legal in DTDs ignoring comments and
4029 * processing instructions, all of which begin with an exclamation
4030 * mark. "<el/>" is not one of them, so the parser should raise an
4031 * error on encountering it.
4032 */
4033 static int XMLCALL
external_entity_param(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)4034 external_entity_param(XML_Parser parser, const XML_Char *context,
4035 const XML_Char *base, const XML_Char *systemId,
4036 const XML_Char *publicId) {
4037 const char *text1 = "<!ELEMENT doc EMPTY>\n"
4038 "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
4039 "<!ENTITY % e2 '%e1;'>\n"
4040 "%e1;\n";
4041 const char *text2 = "<!ELEMENT el EMPTY>\n"
4042 "<el/>\n";
4043 XML_Parser ext_parser;
4044
4045 UNUSED_P(base);
4046 UNUSED_P(publicId);
4047 if (systemId == NULL)
4048 return XML_STATUS_OK;
4049
4050 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4051 if (ext_parser == NULL)
4052 fail("Could not create external entity parser");
4053
4054 if (! xcstrcmp(systemId, XCS("004-1.ent"))) {
4055 if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
4056 != XML_STATUS_ERROR)
4057 fail("Inner DTD with invalid tag not rejected");
4058 if (XML_GetErrorCode(ext_parser) != XML_ERROR_EXTERNAL_ENTITY_HANDLING)
4059 xml_failure(ext_parser);
4060 } else if (! xcstrcmp(systemId, XCS("004-2.ent"))) {
4061 if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE)
4062 != XML_STATUS_ERROR)
4063 fail("Invalid tag in external param not rejected");
4064 if (XML_GetErrorCode(ext_parser) != XML_ERROR_SYNTAX)
4065 xml_failure(ext_parser);
4066 } else {
4067 fail("Unknown system ID");
4068 }
4069
4070 XML_ParserFree(ext_parser);
4071 return XML_STATUS_ERROR;
4072 }
4073
START_TEST(test_invalid_tag_in_dtd)4074 START_TEST(test_invalid_tag_in_dtd) {
4075 const char *text = "<!DOCTYPE doc SYSTEM '004-1.ent'>\n"
4076 "<doc></doc>\n";
4077
4078 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4079 XML_SetExternalEntityRefHandler(g_parser, external_entity_param);
4080 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
4081 "Invalid tag IN DTD external param not rejected");
4082 }
4083 END_TEST
4084
4085 /* Test entities not quite the predefined ones are not mis-recognised */
START_TEST(test_not_predefined_entities)4086 START_TEST(test_not_predefined_entities) {
4087 const char *text[] = {"<doc>&pt;</doc>", "<doc>&amo;</doc>",
4088 "<doc>&quid;</doc>", "<doc>&apod;</doc>", NULL};
4089 int i = 0;
4090
4091 while (text[i] != NULL) {
4092 expect_failure(text[i], XML_ERROR_UNDEFINED_ENTITY,
4093 "Undefined entity not rejected");
4094 XML_ParserReset(g_parser, NULL);
4095 i++;
4096 }
4097 }
4098 END_TEST
4099
4100 /* Test conditional inclusion (IGNORE) */
4101 static int XMLCALL
external_entity_load_ignore(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)4102 external_entity_load_ignore(XML_Parser parser, const XML_Char *context,
4103 const XML_Char *base, const XML_Char *systemId,
4104 const XML_Char *publicId) {
4105 const char *text = "<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>";
4106 XML_Parser ext_parser;
4107
4108 UNUSED_P(base);
4109 UNUSED_P(systemId);
4110 UNUSED_P(publicId);
4111 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4112 if (ext_parser == NULL)
4113 fail("Could not create external entity parser");
4114 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
4115 == XML_STATUS_ERROR)
4116 xml_failure(parser);
4117
4118 XML_ParserFree(ext_parser);
4119 return XML_STATUS_OK;
4120 }
4121
START_TEST(test_ignore_section)4122 START_TEST(test_ignore_section) {
4123 const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
4124 "<doc><e>&entity;</e></doc>";
4125 const XML_Char *expected
4126 = XCS("<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>\n&entity;");
4127 CharData storage;
4128
4129 CharData_Init(&storage);
4130 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4131 XML_SetUserData(g_parser, &storage);
4132 XML_SetExternalEntityRefHandler(g_parser, external_entity_load_ignore);
4133 XML_SetDefaultHandler(g_parser, accumulate_characters);
4134 XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler);
4135 XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler);
4136 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4137 XML_SetStartElementHandler(g_parser, dummy_start_element);
4138 XML_SetEndElementHandler(g_parser, dummy_end_element);
4139 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4140 == XML_STATUS_ERROR)
4141 xml_failure(g_parser);
4142 CharData_CheckXMLChars(&storage, expected);
4143 }
4144 END_TEST
4145
4146 static int XMLCALL
external_entity_load_ignore_utf16(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)4147 external_entity_load_ignore_utf16(XML_Parser parser, const XML_Char *context,
4148 const XML_Char *base,
4149 const XML_Char *systemId,
4150 const XML_Char *publicId) {
4151 const char text[] =
4152 /* <![IGNORE[<!ELEMENT e (#PCDATA)*>]]> */
4153 "<\0!\0[\0I\0G\0N\0O\0R\0E\0[\0"
4154 "<\0!\0E\0L\0E\0M\0E\0N\0T\0 \0e\0 \0"
4155 "(\0#\0P\0C\0D\0A\0T\0A\0)\0*\0>\0]\0]\0>\0";
4156 XML_Parser ext_parser;
4157
4158 UNUSED_P(base);
4159 UNUSED_P(systemId);
4160 UNUSED_P(publicId);
4161 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4162 if (ext_parser == NULL)
4163 fail("Could not create external entity parser");
4164 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)sizeof(text) - 1, XML_TRUE)
4165 == XML_STATUS_ERROR)
4166 xml_failure(parser);
4167
4168 XML_ParserFree(ext_parser);
4169 return XML_STATUS_OK;
4170 }
4171
START_TEST(test_ignore_section_utf16)4172 START_TEST(test_ignore_section_utf16) {
4173 const char text[] =
4174 /* <!DOCTYPE d SYSTEM 's'> */
4175 "<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 "
4176 "\0S\0Y\0S\0T\0E\0M\0 \0'\0s\0'\0>\0\n\0"
4177 /* <d><e>&en;</e></d> */
4178 "<\0d\0>\0<\0e\0>\0&\0e\0n\0;\0<\0/\0e\0>\0<\0/\0d\0>\0";
4179 const XML_Char *expected = XCS("<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>\n&en;");
4180 CharData storage;
4181
4182 CharData_Init(&storage);
4183 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4184 XML_SetUserData(g_parser, &storage);
4185 XML_SetExternalEntityRefHandler(g_parser, external_entity_load_ignore_utf16);
4186 XML_SetDefaultHandler(g_parser, accumulate_characters);
4187 XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler);
4188 XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler);
4189 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4190 XML_SetStartElementHandler(g_parser, dummy_start_element);
4191 XML_SetEndElementHandler(g_parser, dummy_end_element);
4192 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
4193 == XML_STATUS_ERROR)
4194 xml_failure(g_parser);
4195 CharData_CheckXMLChars(&storage, expected);
4196 }
4197 END_TEST
4198
4199 static int XMLCALL
external_entity_load_ignore_utf16_be(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)4200 external_entity_load_ignore_utf16_be(XML_Parser parser, const XML_Char *context,
4201 const XML_Char *base,
4202 const XML_Char *systemId,
4203 const XML_Char *publicId) {
4204 const char text[] =
4205 /* <![IGNORE[<!ELEMENT e (#PCDATA)*>]]> */
4206 "\0<\0!\0[\0I\0G\0N\0O\0R\0E\0["
4207 "\0<\0!\0E\0L\0E\0M\0E\0N\0T\0 \0e\0 "
4208 "\0(\0#\0P\0C\0D\0A\0T\0A\0)\0*\0>\0]\0]\0>";
4209 XML_Parser ext_parser;
4210
4211 UNUSED_P(base);
4212 UNUSED_P(systemId);
4213 UNUSED_P(publicId);
4214 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4215 if (ext_parser == NULL)
4216 fail("Could not create external entity parser");
4217 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)sizeof(text) - 1, XML_TRUE)
4218 == XML_STATUS_ERROR)
4219 xml_failure(parser);
4220
4221 XML_ParserFree(ext_parser);
4222 return XML_STATUS_OK;
4223 }
4224
START_TEST(test_ignore_section_utf16_be)4225 START_TEST(test_ignore_section_utf16_be) {
4226 const char text[] =
4227 /* <!DOCTYPE d SYSTEM 's'> */
4228 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 "
4229 "\0S\0Y\0S\0T\0E\0M\0 \0'\0s\0'\0>\0\n"
4230 /* <d><e>&en;</e></d> */
4231 "\0<\0d\0>\0<\0e\0>\0&\0e\0n\0;\0<\0/\0e\0>\0<\0/\0d\0>";
4232 const XML_Char *expected = XCS("<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>\n&en;");
4233 CharData storage;
4234
4235 CharData_Init(&storage);
4236 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4237 XML_SetUserData(g_parser, &storage);
4238 XML_SetExternalEntityRefHandler(g_parser,
4239 external_entity_load_ignore_utf16_be);
4240 XML_SetDefaultHandler(g_parser, accumulate_characters);
4241 XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler);
4242 XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler);
4243 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4244 XML_SetStartElementHandler(g_parser, dummy_start_element);
4245 XML_SetEndElementHandler(g_parser, dummy_end_element);
4246 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
4247 == XML_STATUS_ERROR)
4248 xml_failure(g_parser);
4249 CharData_CheckXMLChars(&storage, expected);
4250 }
4251 END_TEST
4252
4253 /* Test mis-formatted conditional exclusion */
START_TEST(test_bad_ignore_section)4254 START_TEST(test_bad_ignore_section) {
4255 const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
4256 "<doc><e>&entity;</e></doc>";
4257 ExtFaults faults[]
4258 = {{"<![IGNORE[<!ELEM", "Broken-off declaration not faulted", NULL,
4259 XML_ERROR_SYNTAX},
4260 {"<![IGNORE[\x01]]>", "Invalid XML character not faulted", NULL,
4261 XML_ERROR_INVALID_TOKEN},
4262 {/* FIrst two bytes of a three-byte char */
4263 "<![IGNORE[\xe2\x82", "Partial XML character not faulted", NULL,
4264 XML_ERROR_PARTIAL_CHAR},
4265 {NULL, NULL, NULL, XML_ERROR_NONE}};
4266 ExtFaults *fault;
4267
4268 for (fault = &faults[0]; fault->parse_text != NULL; fault++) {
4269 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4270 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
4271 XML_SetUserData(g_parser, fault);
4272 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
4273 "Incomplete IGNORE section not failed");
4274 XML_ParserReset(g_parser, NULL);
4275 }
4276 }
4277 END_TEST
4278
4279 /* Test recursive parsing */
4280 static int XMLCALL
external_entity_valuer(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)4281 external_entity_valuer(XML_Parser parser, const XML_Char *context,
4282 const XML_Char *base, const XML_Char *systemId,
4283 const XML_Char *publicId) {
4284 const char *text1 = "<!ELEMENT doc EMPTY>\n"
4285 "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
4286 "<!ENTITY % e2 '%e1;'>\n"
4287 "%e1;\n";
4288 XML_Parser ext_parser;
4289
4290 UNUSED_P(base);
4291 UNUSED_P(publicId);
4292 if (systemId == NULL)
4293 return XML_STATUS_OK;
4294 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4295 if (ext_parser == NULL)
4296 fail("Could not create external entity parser");
4297 if (! xcstrcmp(systemId, XCS("004-1.ent"))) {
4298 if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
4299 == XML_STATUS_ERROR)
4300 xml_failure(ext_parser);
4301 } else if (! xcstrcmp(systemId, XCS("004-2.ent"))) {
4302 ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser);
4303 enum XML_Status status;
4304 enum XML_Error error;
4305
4306 status = _XML_Parse_SINGLE_BYTES(ext_parser, fault->parse_text,
4307 (int)strlen(fault->parse_text), XML_TRUE);
4308 if (fault->error == XML_ERROR_NONE) {
4309 if (status == XML_STATUS_ERROR)
4310 xml_failure(ext_parser);
4311 } else {
4312 if (status != XML_STATUS_ERROR)
4313 fail(fault->fail_text);
4314 error = XML_GetErrorCode(ext_parser);
4315 if (error != fault->error
4316 && (fault->error != XML_ERROR_XML_DECL
4317 || error != XML_ERROR_TEXT_DECL))
4318 xml_failure(ext_parser);
4319 }
4320 }
4321
4322 XML_ParserFree(ext_parser);
4323 return XML_STATUS_OK;
4324 }
4325
START_TEST(test_external_entity_values)4326 START_TEST(test_external_entity_values) {
4327 const char *text = "<!DOCTYPE doc SYSTEM '004-1.ent'>\n"
4328 "<doc></doc>\n";
4329 ExtFaults data_004_2[] = {
4330 {"<!ATTLIST doc a1 CDATA 'value'>", NULL, NULL, XML_ERROR_NONE},
4331 {"<!ATTLIST $doc a1 CDATA 'value'>", "Invalid token not faulted", NULL,
4332 XML_ERROR_INVALID_TOKEN},
4333 {"'wombat", "Unterminated string not faulted", NULL,
4334 XML_ERROR_UNCLOSED_TOKEN},
4335 {"\xe2\x82", "Partial UTF-8 character not faulted", NULL,
4336 XML_ERROR_PARTIAL_CHAR},
4337 {"<?xml version='1.0' encoding='utf-8'?>\n", NULL, NULL, XML_ERROR_NONE},
4338 {"<?xml?>", "Malformed XML declaration not faulted", NULL,
4339 XML_ERROR_XML_DECL},
4340 {/* UTF-8 BOM */
4341 "\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>", NULL, NULL,
4342 XML_ERROR_NONE},
4343 {"<?xml version='1.0' encoding='utf-8'?>\n$",
4344 "Invalid token after text declaration not faulted", NULL,
4345 XML_ERROR_INVALID_TOKEN},
4346 {"<?xml version='1.0' encoding='utf-8'?>\n'wombat",
4347 "Unterminated string after text decl not faulted", NULL,
4348 XML_ERROR_UNCLOSED_TOKEN},
4349 {"<?xml version='1.0' encoding='utf-8'?>\n\xe2\x82",
4350 "Partial UTF-8 character after text decl not faulted", NULL,
4351 XML_ERROR_PARTIAL_CHAR},
4352 {"%e1;", "Recursive parameter entity not faulted", NULL,
4353 XML_ERROR_RECURSIVE_ENTITY_REF},
4354 {NULL, NULL, NULL, XML_ERROR_NONE}};
4355 int i;
4356
4357 for (i = 0; data_004_2[i].parse_text != NULL; i++) {
4358 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4359 XML_SetExternalEntityRefHandler(g_parser, external_entity_valuer);
4360 XML_SetUserData(g_parser, &data_004_2[i]);
4361 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4362 == XML_STATUS_ERROR)
4363 xml_failure(g_parser);
4364 XML_ParserReset(g_parser, NULL);
4365 }
4366 }
4367 END_TEST
4368
4369 /* Test the recursive parse interacts with a not standalone handler */
4370 static int XMLCALL
external_entity_not_standalone(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)4371 external_entity_not_standalone(XML_Parser parser, const XML_Char *context,
4372 const XML_Char *base, const XML_Char *systemId,
4373 const XML_Char *publicId) {
4374 const char *text1 = "<!ELEMENT doc EMPTY>\n"
4375 "<!ENTITY % e1 SYSTEM 'bar'>\n"
4376 "%e1;\n";
4377 const char *text2 = "<!ATTLIST doc a1 CDATA 'value'>";
4378 XML_Parser ext_parser;
4379
4380 UNUSED_P(base);
4381 UNUSED_P(publicId);
4382 if (systemId == NULL)
4383 return XML_STATUS_OK;
4384 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4385 if (ext_parser == NULL)
4386 fail("Could not create external entity parser");
4387 if (! xcstrcmp(systemId, XCS("foo"))) {
4388 XML_SetNotStandaloneHandler(ext_parser, reject_not_standalone_handler);
4389 if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
4390 != XML_STATUS_ERROR)
4391 fail("Expected not standalone rejection");
4392 if (XML_GetErrorCode(ext_parser) != XML_ERROR_NOT_STANDALONE)
4393 xml_failure(ext_parser);
4394 XML_SetNotStandaloneHandler(ext_parser, NULL);
4395 XML_ParserFree(ext_parser);
4396 return XML_STATUS_ERROR;
4397 } else if (! xcstrcmp(systemId, XCS("bar"))) {
4398 if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE)
4399 == XML_STATUS_ERROR)
4400 xml_failure(ext_parser);
4401 }
4402
4403 XML_ParserFree(ext_parser);
4404 return XML_STATUS_OK;
4405 }
4406
START_TEST(test_ext_entity_not_standalone)4407 START_TEST(test_ext_entity_not_standalone) {
4408 const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
4409 "<doc></doc>";
4410
4411 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4412 XML_SetExternalEntityRefHandler(g_parser, external_entity_not_standalone);
4413 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
4414 "Standalone rejection not caught");
4415 }
4416 END_TEST
4417
4418 static int XMLCALL
external_entity_value_aborter(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)4419 external_entity_value_aborter(XML_Parser parser, const XML_Char *context,
4420 const XML_Char *base, const XML_Char *systemId,
4421 const XML_Char *publicId) {
4422 const char *text1 = "<!ELEMENT doc EMPTY>\n"
4423 "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
4424 "<!ENTITY % e2 '%e1;'>\n"
4425 "%e1;\n";
4426 const char *text2 = "<?xml version='1.0' encoding='utf-8'?>";
4427 XML_Parser ext_parser;
4428
4429 UNUSED_P(base);
4430 UNUSED_P(publicId);
4431 if (systemId == NULL)
4432 return XML_STATUS_OK;
4433 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4434 if (ext_parser == NULL)
4435 fail("Could not create external entity parser");
4436 if (! xcstrcmp(systemId, XCS("004-1.ent"))) {
4437 if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
4438 == XML_STATUS_ERROR)
4439 xml_failure(ext_parser);
4440 }
4441 if (! xcstrcmp(systemId, XCS("004-2.ent"))) {
4442 XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
4443 XML_SetUserData(ext_parser, ext_parser);
4444 if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE)
4445 != XML_STATUS_ERROR)
4446 fail("Aborted parse not faulted");
4447 if (XML_GetErrorCode(ext_parser) != XML_ERROR_ABORTED)
4448 xml_failure(ext_parser);
4449 }
4450
4451 XML_ParserFree(ext_parser);
4452 return XML_STATUS_OK;
4453 }
4454
START_TEST(test_ext_entity_value_abort)4455 START_TEST(test_ext_entity_value_abort) {
4456 const char *text = "<!DOCTYPE doc SYSTEM '004-1.ent'>\n"
4457 "<doc></doc>\n";
4458
4459 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4460 XML_SetExternalEntityRefHandler(g_parser, external_entity_value_aborter);
4461 resumable = XML_FALSE;
4462 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4463 == XML_STATUS_ERROR)
4464 xml_failure(g_parser);
4465 }
4466 END_TEST
4467
START_TEST(test_bad_public_doctype)4468 START_TEST(test_bad_public_doctype) {
4469 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
4470 "<!DOCTYPE doc PUBLIC '{BadName}' 'test'>\n"
4471 "<doc></doc>";
4472
4473 /* Setting a handler provokes a particular code path */
4474 XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_handler,
4475 dummy_end_doctype_handler);
4476 expect_failure(text, XML_ERROR_PUBLICID, "Bad Public ID not failed");
4477 }
4478 END_TEST
4479
4480 /* Test based on ibm/valid/P32/ibm32v04.xml */
START_TEST(test_attribute_enum_value)4481 START_TEST(test_attribute_enum_value) {
4482 const char *text = "<?xml version='1.0' standalone='no'?>\n"
4483 "<!DOCTYPE animal SYSTEM 'test.dtd'>\n"
4484 "<animal>This is a \n <a/> \n\nyellow tiger</animal>";
4485 ExtTest dtd_data
4486 = {"<!ELEMENT animal (#PCDATA|a)*>\n"
4487 "<!ELEMENT a EMPTY>\n"
4488 "<!ATTLIST animal xml:space (default|preserve) 'preserve'>",
4489 NULL, NULL};
4490 const XML_Char *expected = XCS("This is a \n \n\nyellow tiger");
4491
4492 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
4493 XML_SetUserData(g_parser, &dtd_data);
4494 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4495 /* An attribute list handler provokes a different code path */
4496 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
4497 run_ext_character_check(text, &dtd_data, expected);
4498 }
4499 END_TEST
4500
4501 /* Slightly bizarrely, the library seems to silently ignore entity
4502 * definitions for predefined entities, even when they are wrong. The
4503 * language of the XML 1.0 spec is somewhat unhelpful as to what ought
4504 * to happen, so this is currently treated as acceptable.
4505 */
START_TEST(test_predefined_entity_redefinition)4506 START_TEST(test_predefined_entity_redefinition) {
4507 const char *text = "<!DOCTYPE doc [\n"
4508 "<!ENTITY apos 'foo'>\n"
4509 "]>\n"
4510 "<doc>'</doc>";
4511 run_character_check(text, XCS("'"));
4512 }
4513 END_TEST
4514
4515 /* Test that the parser stops processing the DTD after an unresolved
4516 * parameter entity is encountered.
4517 */
START_TEST(test_dtd_stop_processing)4518 START_TEST(test_dtd_stop_processing) {
4519 const char *text = "<!DOCTYPE doc [\n"
4520 "%foo;\n"
4521 "<!ENTITY bar 'bas'>\n"
4522 "]><doc/>";
4523
4524 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
4525 dummy_handler_flags = 0;
4526 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4527 == XML_STATUS_ERROR)
4528 xml_failure(g_parser);
4529 if (dummy_handler_flags != 0)
4530 fail("DTD processing still going after undefined PE");
4531 }
4532 END_TEST
4533
4534 /* Test public notations with no system ID */
START_TEST(test_public_notation_no_sysid)4535 START_TEST(test_public_notation_no_sysid) {
4536 const char *text = "<!DOCTYPE doc [\n"
4537 "<!NOTATION note PUBLIC 'foo'>\n"
4538 "<!ELEMENT doc EMPTY>\n"
4539 "]>\n<doc/>";
4540
4541 dummy_handler_flags = 0;
4542 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
4543 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4544 == XML_STATUS_ERROR)
4545 xml_failure(g_parser);
4546 if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG)
4547 fail("Notation declaration handler not called");
4548 }
4549 END_TEST
4550
4551 static void XMLCALL
record_element_start_handler(void * userData,const XML_Char * name,const XML_Char ** atts)4552 record_element_start_handler(void *userData, const XML_Char *name,
4553 const XML_Char **atts) {
4554 UNUSED_P(atts);
4555 CharData_AppendXMLChars((CharData *)userData, name, (int)xcstrlen(name));
4556 }
4557
START_TEST(test_nested_groups)4558 START_TEST(test_nested_groups) {
4559 const char *text
4560 = "<!DOCTYPE doc [\n"
4561 "<!ELEMENT doc "
4562 /* Sixteen elements per line */
4563 "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,"
4564 "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?"
4565 "))))))))))))))))))))))))))))))))>\n"
4566 "<!ELEMENT e EMPTY>"
4567 "]>\n"
4568 "<doc><e/></doc>";
4569 CharData storage;
4570
4571 CharData_Init(&storage);
4572 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4573 XML_SetStartElementHandler(g_parser, record_element_start_handler);
4574 XML_SetUserData(g_parser, &storage);
4575 dummy_handler_flags = 0;
4576 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4577 == XML_STATUS_ERROR)
4578 xml_failure(g_parser);
4579 CharData_CheckXMLChars(&storage, XCS("doce"));
4580 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
4581 fail("Element handler not fired");
4582 }
4583 END_TEST
4584
START_TEST(test_group_choice)4585 START_TEST(test_group_choice) {
4586 const char *text = "<!DOCTYPE doc [\n"
4587 "<!ELEMENT doc (a|b|c)+>\n"
4588 "<!ELEMENT a EMPTY>\n"
4589 "<!ELEMENT b (#PCDATA)>\n"
4590 "<!ELEMENT c ANY>\n"
4591 "]>\n"
4592 "<doc>\n"
4593 "<a/>\n"
4594 "<b attr='foo'>This is a foo</b>\n"
4595 "<c></c>\n"
4596 "</doc>\n";
4597
4598 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4599 dummy_handler_flags = 0;
4600 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4601 == XML_STATUS_ERROR)
4602 xml_failure(g_parser);
4603 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
4604 fail("Element handler flag not raised");
4605 }
4606 END_TEST
4607
4608 static int XMLCALL
external_entity_public(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)4609 external_entity_public(XML_Parser parser, const XML_Char *context,
4610 const XML_Char *base, const XML_Char *systemId,
4611 const XML_Char *publicId) {
4612 const char *text1 = (const char *)XML_GetUserData(parser);
4613 const char *text2 = "<!ATTLIST doc a CDATA 'value'>";
4614 const char *text = NULL;
4615 XML_Parser ext_parser;
4616 int parse_res;
4617
4618 UNUSED_P(base);
4619 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4620 if (ext_parser == NULL)
4621 return XML_STATUS_ERROR;
4622 if (systemId != NULL && ! xcstrcmp(systemId, XCS("http://example.org/"))) {
4623 text = text1;
4624 } else if (publicId != NULL && ! xcstrcmp(publicId, XCS("foo"))) {
4625 text = text2;
4626 } else
4627 fail("Unexpected parameters to external entity parser");
4628 assert(text != NULL);
4629 parse_res
4630 = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
4631 XML_ParserFree(ext_parser);
4632 return parse_res;
4633 }
4634
START_TEST(test_standalone_parameter_entity)4635 START_TEST(test_standalone_parameter_entity) {
4636 const char *text = "<?xml version='1.0' standalone='yes'?>\n"
4637 "<!DOCTYPE doc SYSTEM 'http://example.org/' [\n"
4638 "<!ENTITY % entity '<!ELEMENT doc (#PCDATA)>'>\n"
4639 "%entity;\n"
4640 "]>\n"
4641 "<doc></doc>";
4642 char dtd_data[] = "<!ENTITY % e1 'foo'>\n";
4643
4644 XML_SetUserData(g_parser, dtd_data);
4645 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4646 XML_SetExternalEntityRefHandler(g_parser, external_entity_public);
4647 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4648 == XML_STATUS_ERROR)
4649 xml_failure(g_parser);
4650 }
4651 END_TEST
4652
4653 /* Test skipping of parameter entity in an external DTD */
4654 /* Derived from ibm/invalid/P69/ibm69i01.xml */
START_TEST(test_skipped_parameter_entity)4655 START_TEST(test_skipped_parameter_entity) {
4656 const char *text = "<?xml version='1.0'?>\n"
4657 "<!DOCTYPE root SYSTEM 'http://example.org/dtd.ent' [\n"
4658 "<!ELEMENT root (#PCDATA|a)* >\n"
4659 "]>\n"
4660 "<root></root>";
4661 ExtTest dtd_data = {"%pe2;", NULL, NULL};
4662
4663 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
4664 XML_SetUserData(g_parser, &dtd_data);
4665 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4666 XML_SetSkippedEntityHandler(g_parser, dummy_skip_handler);
4667 dummy_handler_flags = 0;
4668 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4669 == XML_STATUS_ERROR)
4670 xml_failure(g_parser);
4671 if (dummy_handler_flags != DUMMY_SKIP_HANDLER_FLAG)
4672 fail("Skip handler not executed");
4673 }
4674 END_TEST
4675
4676 /* Test recursive parameter entity definition rejected in external DTD */
START_TEST(test_recursive_external_parameter_entity)4677 START_TEST(test_recursive_external_parameter_entity) {
4678 const char *text = "<?xml version='1.0'?>\n"
4679 "<!DOCTYPE root SYSTEM 'http://example.org/dtd.ent' [\n"
4680 "<!ELEMENT root (#PCDATA|a)* >\n"
4681 "]>\n"
4682 "<root></root>";
4683 ExtFaults dtd_data = {"<!ENTITY % pe2 '%pe2;'>\n%pe2;",
4684 "Recursive external parameter entity not faulted", NULL,
4685 XML_ERROR_RECURSIVE_ENTITY_REF};
4686
4687 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
4688 XML_SetUserData(g_parser, &dtd_data);
4689 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4690 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
4691 "Recursive external parameter not spotted");
4692 }
4693 END_TEST
4694
4695 /* Test undefined parameter entity in external entity handler */
4696 static int XMLCALL
external_entity_devaluer(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)4697 external_entity_devaluer(XML_Parser parser, const XML_Char *context,
4698 const XML_Char *base, const XML_Char *systemId,
4699 const XML_Char *publicId) {
4700 const char *text = "<!ELEMENT doc EMPTY>\n"
4701 "<!ENTITY % e1 SYSTEM 'bar'>\n"
4702 "%e1;\n";
4703 XML_Parser ext_parser;
4704 intptr_t clear_handler = (intptr_t)XML_GetUserData(parser);
4705
4706 UNUSED_P(base);
4707 UNUSED_P(publicId);
4708 if (systemId == NULL || ! xcstrcmp(systemId, XCS("bar")))
4709 return XML_STATUS_OK;
4710 if (xcstrcmp(systemId, XCS("foo")))
4711 fail("Unexpected system ID");
4712 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4713 if (ext_parser == NULL)
4714 fail("Could note create external entity parser");
4715 if (clear_handler)
4716 XML_SetExternalEntityRefHandler(ext_parser, NULL);
4717 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
4718 == XML_STATUS_ERROR)
4719 xml_failure(ext_parser);
4720
4721 XML_ParserFree(ext_parser);
4722 return XML_STATUS_OK;
4723 }
4724
START_TEST(test_undefined_ext_entity_in_external_dtd)4725 START_TEST(test_undefined_ext_entity_in_external_dtd) {
4726 const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
4727 "<doc></doc>\n";
4728
4729 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4730 XML_SetExternalEntityRefHandler(g_parser, external_entity_devaluer);
4731 XML_SetUserData(g_parser, (void *)(intptr_t)XML_FALSE);
4732 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4733 == XML_STATUS_ERROR)
4734 xml_failure(g_parser);
4735
4736 /* Now repeat without the external entity ref handler invoking
4737 * another copy of itself.
4738 */
4739 XML_ParserReset(g_parser, NULL);
4740 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4741 XML_SetExternalEntityRefHandler(g_parser, external_entity_devaluer);
4742 XML_SetUserData(g_parser, (void *)(intptr_t)XML_TRUE);
4743 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4744 == XML_STATUS_ERROR)
4745 xml_failure(g_parser);
4746 }
4747 END_TEST
4748
4749 static void XMLCALL
aborting_xdecl_handler(void * userData,const XML_Char * version,const XML_Char * encoding,int standalone)4750 aborting_xdecl_handler(void *userData, const XML_Char *version,
4751 const XML_Char *encoding, int standalone) {
4752 UNUSED_P(userData);
4753 UNUSED_P(version);
4754 UNUSED_P(encoding);
4755 UNUSED_P(standalone);
4756 XML_StopParser(g_parser, resumable);
4757 XML_SetXmlDeclHandler(g_parser, NULL);
4758 }
4759
4760 /* Test suspending the parse on receiving an XML declaration works */
START_TEST(test_suspend_xdecl)4761 START_TEST(test_suspend_xdecl) {
4762 const char *text = long_character_data_text;
4763
4764 XML_SetXmlDeclHandler(g_parser, aborting_xdecl_handler);
4765 resumable = XML_TRUE;
4766 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4767 != XML_STATUS_SUSPENDED)
4768 xml_failure(g_parser);
4769 if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE)
4770 xml_failure(g_parser);
4771 /* Attempt to start a new parse while suspended */
4772 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
4773 != XML_STATUS_ERROR)
4774 fail("Attempt to parse while suspended not faulted");
4775 if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED)
4776 fail("Suspended parse not faulted with correct error");
4777 }
4778 END_TEST
4779
4780 /* Test aborting the parse in an epilog works */
4781 static void XMLCALL
selective_aborting_default_handler(void * userData,const XML_Char * s,int len)4782 selective_aborting_default_handler(void *userData, const XML_Char *s, int len) {
4783 const XML_Char *match = (const XML_Char *)userData;
4784
4785 if (match == NULL
4786 || (xcstrlen(match) == (unsigned)len && ! xcstrncmp(match, s, len))) {
4787 XML_StopParser(g_parser, resumable);
4788 XML_SetDefaultHandler(g_parser, NULL);
4789 }
4790 }
4791
START_TEST(test_abort_epilog)4792 START_TEST(test_abort_epilog) {
4793 const char *text = "<doc></doc>\n\r\n";
4794 XML_Char match[] = XCS("\r");
4795
4796 XML_SetDefaultHandler(g_parser, selective_aborting_default_handler);
4797 XML_SetUserData(g_parser, match);
4798 resumable = XML_FALSE;
4799 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4800 != XML_STATUS_ERROR)
4801 fail("Abort not triggered");
4802 if (XML_GetErrorCode(g_parser) != XML_ERROR_ABORTED)
4803 xml_failure(g_parser);
4804 }
4805 END_TEST
4806
4807 /* Test a different code path for abort in the epilog */
START_TEST(test_abort_epilog_2)4808 START_TEST(test_abort_epilog_2) {
4809 const char *text = "<doc></doc>\n";
4810 XML_Char match[] = XCS("\n");
4811
4812 XML_SetDefaultHandler(g_parser, selective_aborting_default_handler);
4813 XML_SetUserData(g_parser, match);
4814 resumable = XML_FALSE;
4815 expect_failure(text, XML_ERROR_ABORTED, "Abort not triggered");
4816 }
4817 END_TEST
4818
4819 /* Test suspension from the epilog */
START_TEST(test_suspend_epilog)4820 START_TEST(test_suspend_epilog) {
4821 const char *text = "<doc></doc>\n";
4822 XML_Char match[] = XCS("\n");
4823
4824 XML_SetDefaultHandler(g_parser, selective_aborting_default_handler);
4825 XML_SetUserData(g_parser, match);
4826 resumable = XML_TRUE;
4827 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4828 != XML_STATUS_SUSPENDED)
4829 xml_failure(g_parser);
4830 }
4831 END_TEST
4832
4833 static void XMLCALL
suspending_end_handler(void * userData,const XML_Char * s)4834 suspending_end_handler(void *userData, const XML_Char *s) {
4835 UNUSED_P(s);
4836 XML_StopParser((XML_Parser)userData, 1);
4837 }
4838
START_TEST(test_suspend_in_sole_empty_tag)4839 START_TEST(test_suspend_in_sole_empty_tag) {
4840 const char *text = "<doc/>";
4841 enum XML_Status rc;
4842
4843 XML_SetEndElementHandler(g_parser, suspending_end_handler);
4844 XML_SetUserData(g_parser, g_parser);
4845 rc = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE);
4846 if (rc == XML_STATUS_ERROR)
4847 xml_failure(g_parser);
4848 else if (rc != XML_STATUS_SUSPENDED)
4849 fail("Suspend not triggered");
4850 rc = XML_ResumeParser(g_parser);
4851 if (rc == XML_STATUS_ERROR)
4852 xml_failure(g_parser);
4853 else if (rc != XML_STATUS_OK)
4854 fail("Resume failed");
4855 }
4856 END_TEST
4857
START_TEST(test_unfinished_epilog)4858 START_TEST(test_unfinished_epilog) {
4859 const char *text = "<doc></doc><";
4860
4861 expect_failure(text, XML_ERROR_UNCLOSED_TOKEN,
4862 "Incomplete epilog entry not faulted");
4863 }
4864 END_TEST
4865
START_TEST(test_partial_char_in_epilog)4866 START_TEST(test_partial_char_in_epilog) {
4867 const char *text = "<doc></doc>\xe2\x82";
4868
4869 /* First check that no fault is raised if the parse is not finished */
4870 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
4871 == XML_STATUS_ERROR)
4872 xml_failure(g_parser);
4873 /* Now check that it is faulted once we finish */
4874 if (XML_ParseBuffer(g_parser, 0, XML_TRUE) != XML_STATUS_ERROR)
4875 fail("Partial character in epilog not faulted");
4876 if (XML_GetErrorCode(g_parser) != XML_ERROR_PARTIAL_CHAR)
4877 xml_failure(g_parser);
4878 }
4879 END_TEST
4880
START_TEST(test_hash_collision)4881 START_TEST(test_hash_collision) {
4882 /* For full coverage of the lookup routine, we need to ensure a
4883 * hash collision even though we can only tell that we have one
4884 * through breakpoint debugging or coverage statistics. The
4885 * following will cause a hash collision on machines with a 64-bit
4886 * long type; others will have to experiment. The full coverage
4887 * tests invoked from qa.sh usually provide a hash collision, but
4888 * not always. This is an attempt to provide insurance.
4889 */
4890 #define COLLIDING_HASH_SALT (unsigned long)_SIP_ULL(0xffffffffU, 0xff99fc90U)
4891 const char *text
4892 = "<doc>\n"
4893 "<a1/><a2/><a3/><a4/><a5/><a6/><a7/><a8/>\n"
4894 "<b1></b1><b2 attr='foo'>This is a foo</b2><b3></b3><b4></b4>\n"
4895 "<b5></b5><b6></b6><b7></b7><b8></b8>\n"
4896 "<c1/><c2/><c3/><c4/><c5/><c6/><c7/><c8/>\n"
4897 "<d1/><d2/><d3/><d4/><d5/><d6/><d7/>\n"
4898 "<d8>This triggers the table growth and collides with b2</d8>\n"
4899 "</doc>\n";
4900
4901 XML_SetHashSalt(g_parser, COLLIDING_HASH_SALT);
4902 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4903 == XML_STATUS_ERROR)
4904 xml_failure(g_parser);
4905 }
4906 END_TEST
4907 #undef COLLIDING_HASH_SALT
4908
4909 /* Test resuming a parse suspended in entity substitution */
4910 static void XMLCALL
start_element_suspender(void * userData,const XML_Char * name,const XML_Char ** atts)4911 start_element_suspender(void *userData, const XML_Char *name,
4912 const XML_Char **atts) {
4913 UNUSED_P(userData);
4914 UNUSED_P(atts);
4915 if (! xcstrcmp(name, XCS("suspend")))
4916 XML_StopParser(g_parser, XML_TRUE);
4917 if (! xcstrcmp(name, XCS("abort")))
4918 XML_StopParser(g_parser, XML_FALSE);
4919 }
4920
START_TEST(test_suspend_resume_internal_entity)4921 START_TEST(test_suspend_resume_internal_entity) {
4922 const char *text
4923 = "<!DOCTYPE doc [\n"
4924 "<!ENTITY foo '<suspend>Hi<suspend>Ho</suspend></suspend>'>\n"
4925 "]>\n"
4926 "<doc>&foo;</doc>\n";
4927 const XML_Char *expected1 = XCS("Hi");
4928 const XML_Char *expected2 = XCS("HiHo");
4929 CharData storage;
4930
4931 CharData_Init(&storage);
4932 XML_SetStartElementHandler(g_parser, start_element_suspender);
4933 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
4934 XML_SetUserData(g_parser, &storage);
4935 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
4936 != XML_STATUS_SUSPENDED)
4937 xml_failure(g_parser);
4938 CharData_CheckXMLChars(&storage, XCS(""));
4939 if (XML_ResumeParser(g_parser) != XML_STATUS_SUSPENDED)
4940 xml_failure(g_parser);
4941 CharData_CheckXMLChars(&storage, expected1);
4942 if (XML_ResumeParser(g_parser) != XML_STATUS_OK)
4943 xml_failure(g_parser);
4944 CharData_CheckXMLChars(&storage, expected2);
4945 }
4946 END_TEST
4947
4948 void
suspending_comment_handler(void * userData,const XML_Char * data)4949 suspending_comment_handler(void *userData, const XML_Char *data) {
4950 UNUSED_P(data);
4951 XML_Parser parser = (XML_Parser)userData;
4952 XML_StopParser(parser, XML_TRUE);
4953 }
4954
START_TEST(test_suspend_resume_internal_entity_issue_629)4955 START_TEST(test_suspend_resume_internal_entity_issue_629) {
4956 const char *const text
4957 = "<!DOCTYPE a [<!ENTITY e '<!--COMMENT-->a'>]><a>&e;<b>\n"
4958 "<"
4959 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4960 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4961 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4962 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4963 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4964 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4965 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4966 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4967 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4968 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4969 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4970 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4971 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4972 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4973 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4974 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4975 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4976 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4977 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4978 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4979 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4980 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4981 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4982 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4983 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4984 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4985 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4986 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4987 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4988 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4989 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4990 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4991 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4992 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4993 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4994 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4995 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4996 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4997 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4998 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4999 "/>"
5000 "</b></a>";
5001 const size_t firstChunkSizeBytes = 54;
5002
5003 XML_Parser parser = XML_ParserCreate(NULL);
5004 XML_SetUserData(parser, parser);
5005 XML_SetCommentHandler(parser, suspending_comment_handler);
5006
5007 if (XML_Parse(parser, text, (int)firstChunkSizeBytes, XML_FALSE)
5008 != XML_STATUS_SUSPENDED)
5009 xml_failure(parser);
5010 if (XML_ResumeParser(parser) != XML_STATUS_OK)
5011 xml_failure(parser);
5012 if (XML_Parse(parser, text + firstChunkSizeBytes,
5013 (int)(strlen(text) - firstChunkSizeBytes), XML_TRUE)
5014 != XML_STATUS_OK)
5015 xml_failure(parser);
5016 XML_ParserFree(parser);
5017 }
5018 END_TEST
5019
5020 /* Test syntax error is caught at parse resumption */
START_TEST(test_resume_entity_with_syntax_error)5021 START_TEST(test_resume_entity_with_syntax_error) {
5022 const char *text = "<!DOCTYPE doc [\n"
5023 "<!ENTITY foo '<suspend>Hi</wombat>'>\n"
5024 "]>\n"
5025 "<doc>&foo;</doc>\n";
5026
5027 XML_SetStartElementHandler(g_parser, start_element_suspender);
5028 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
5029 != XML_STATUS_SUSPENDED)
5030 xml_failure(g_parser);
5031 if (XML_ResumeParser(g_parser) != XML_STATUS_ERROR)
5032 fail("Syntax error in entity not faulted");
5033 if (XML_GetErrorCode(g_parser) != XML_ERROR_TAG_MISMATCH)
5034 xml_failure(g_parser);
5035 }
5036 END_TEST
5037
5038 /* Test suspending and resuming in a parameter entity substitution */
5039 static void XMLCALL
element_decl_suspender(void * userData,const XML_Char * name,XML_Content * model)5040 element_decl_suspender(void *userData, const XML_Char *name,
5041 XML_Content *model) {
5042 UNUSED_P(userData);
5043 UNUSED_P(name);
5044 XML_StopParser(g_parser, XML_TRUE);
5045 XML_FreeContentModel(g_parser, model);
5046 }
5047
START_TEST(test_suspend_resume_parameter_entity)5048 START_TEST(test_suspend_resume_parameter_entity) {
5049 const char *text = "<!DOCTYPE doc [\n"
5050 "<!ENTITY % foo '<!ELEMENT doc (#PCDATA)*>'>\n"
5051 "%foo;\n"
5052 "]>\n"
5053 "<doc>Hello, world</doc>";
5054 const XML_Char *expected = XCS("Hello, world");
5055 CharData storage;
5056
5057 CharData_Init(&storage);
5058 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5059 XML_SetElementDeclHandler(g_parser, element_decl_suspender);
5060 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
5061 XML_SetUserData(g_parser, &storage);
5062 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
5063 != XML_STATUS_SUSPENDED)
5064 xml_failure(g_parser);
5065 CharData_CheckXMLChars(&storage, XCS(""));
5066 if (XML_ResumeParser(g_parser) != XML_STATUS_OK)
5067 xml_failure(g_parser);
5068 CharData_CheckXMLChars(&storage, expected);
5069 }
5070 END_TEST
5071
5072 /* Test attempting to use parser after an error is faulted */
START_TEST(test_restart_on_error)5073 START_TEST(test_restart_on_error) {
5074 const char *text = "<$doc><doc></doc>";
5075
5076 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
5077 != XML_STATUS_ERROR)
5078 fail("Invalid tag name not faulted");
5079 if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
5080 xml_failure(g_parser);
5081 if (XML_Parse(g_parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR)
5082 fail("Restarting invalid parse not faulted");
5083 if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
5084 xml_failure(g_parser);
5085 }
5086 END_TEST
5087
5088 /* Test that angle brackets in an attribute default value are faulted */
START_TEST(test_reject_lt_in_attribute_value)5089 START_TEST(test_reject_lt_in_attribute_value) {
5090 const char *text = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '<bar>'>]>\n"
5091 "<doc></doc>";
5092
5093 expect_failure(text, XML_ERROR_INVALID_TOKEN,
5094 "Bad attribute default not faulted");
5095 }
5096 END_TEST
5097
START_TEST(test_reject_unfinished_param_in_att_value)5098 START_TEST(test_reject_unfinished_param_in_att_value) {
5099 const char *text = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '&foo'>]>\n"
5100 "<doc></doc>";
5101
5102 expect_failure(text, XML_ERROR_INVALID_TOKEN,
5103 "Bad attribute default not faulted");
5104 }
5105 END_TEST
5106
START_TEST(test_trailing_cr_in_att_value)5107 START_TEST(test_trailing_cr_in_att_value) {
5108 const char *text = "<doc a='value\r'/>";
5109
5110 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5111 == XML_STATUS_ERROR)
5112 xml_failure(g_parser);
5113 }
5114 END_TEST
5115
5116 /* Try parsing a general entity within a parameter entity in a
5117 * standalone internal DTD. Covers a corner case in the parser.
5118 */
START_TEST(test_standalone_internal_entity)5119 START_TEST(test_standalone_internal_entity) {
5120 const char *text = "<?xml version='1.0' standalone='yes' ?>\n"
5121 "<!DOCTYPE doc [\n"
5122 " <!ELEMENT doc (#PCDATA)>\n"
5123 " <!ENTITY % pe '<!ATTLIST doc att2 CDATA \"≥\">'>\n"
5124 " <!ENTITY ge 'AttDefaultValue'>\n"
5125 " %pe;\n"
5126 "]>\n"
5127 "<doc att2='any'/>";
5128
5129 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5130 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5131 == XML_STATUS_ERROR)
5132 xml_failure(g_parser);
5133 }
5134 END_TEST
5135
5136 /* Test that a reference to an unknown external entity is skipped */
START_TEST(test_skipped_external_entity)5137 START_TEST(test_skipped_external_entity) {
5138 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
5139 "<doc></doc>\n";
5140 ExtTest test_data = {"<!ELEMENT doc EMPTY>\n"
5141 "<!ENTITY % e2 '%e1;'>\n",
5142 NULL, NULL};
5143
5144 XML_SetUserData(g_parser, &test_data);
5145 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5146 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
5147 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5148 == XML_STATUS_ERROR)
5149 xml_failure(g_parser);
5150 }
5151 END_TEST
5152
5153 /* Test a different form of unknown external entity */
5154 typedef struct ext_hdlr_data {
5155 const char *parse_text;
5156 XML_ExternalEntityRefHandler handler;
5157 } ExtHdlrData;
5158
5159 static int XMLCALL
external_entity_oneshot_loader(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)5160 external_entity_oneshot_loader(XML_Parser parser, const XML_Char *context,
5161 const XML_Char *base, const XML_Char *systemId,
5162 const XML_Char *publicId) {
5163 ExtHdlrData *test_data = (ExtHdlrData *)XML_GetUserData(parser);
5164 XML_Parser ext_parser;
5165
5166 UNUSED_P(base);
5167 UNUSED_P(systemId);
5168 UNUSED_P(publicId);
5169 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
5170 if (ext_parser == NULL)
5171 fail("Could not create external entity parser.");
5172 /* Use the requested entity parser for further externals */
5173 XML_SetExternalEntityRefHandler(ext_parser, test_data->handler);
5174 if (_XML_Parse_SINGLE_BYTES(ext_parser, test_data->parse_text,
5175 (int)strlen(test_data->parse_text), XML_TRUE)
5176 == XML_STATUS_ERROR) {
5177 xml_failure(ext_parser);
5178 }
5179
5180 XML_ParserFree(ext_parser);
5181 return XML_STATUS_OK;
5182 }
5183
START_TEST(test_skipped_null_loaded_ext_entity)5184 START_TEST(test_skipped_null_loaded_ext_entity) {
5185 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n"
5186 "<doc />";
5187 ExtHdlrData test_data
5188 = {"<!ENTITY % pe1 SYSTEM 'http://example.org/two.ent'>\n"
5189 "<!ENTITY % pe2 '%pe1;'>\n"
5190 "%pe2;\n",
5191 external_entity_null_loader};
5192
5193 XML_SetUserData(g_parser, &test_data);
5194 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5195 XML_SetExternalEntityRefHandler(g_parser, external_entity_oneshot_loader);
5196 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5197 == XML_STATUS_ERROR)
5198 xml_failure(g_parser);
5199 }
5200 END_TEST
5201
START_TEST(test_skipped_unloaded_ext_entity)5202 START_TEST(test_skipped_unloaded_ext_entity) {
5203 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n"
5204 "<doc />";
5205 ExtHdlrData test_data
5206 = {"<!ENTITY % pe1 SYSTEM 'http://example.org/two.ent'>\n"
5207 "<!ENTITY % pe2 '%pe1;'>\n"
5208 "%pe2;\n",
5209 NULL};
5210
5211 XML_SetUserData(g_parser, &test_data);
5212 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5213 XML_SetExternalEntityRefHandler(g_parser, external_entity_oneshot_loader);
5214 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5215 == XML_STATUS_ERROR)
5216 xml_failure(g_parser);
5217 }
5218 END_TEST
5219
5220 /* Test that a parameter entity value ending with a carriage return
5221 * has it translated internally into a newline.
5222 */
START_TEST(test_param_entity_with_trailing_cr)5223 START_TEST(test_param_entity_with_trailing_cr) {
5224 #define PARAM_ENTITY_NAME "pe"
5225 #define PARAM_ENTITY_CORE_VALUE "<!ATTLIST doc att CDATA \"default\">"
5226 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
5227 "<doc/>";
5228 ExtTest test_data
5229 = {"<!ENTITY % " PARAM_ENTITY_NAME " '" PARAM_ENTITY_CORE_VALUE "\r'>\n"
5230 "%" PARAM_ENTITY_NAME ";\n",
5231 NULL, NULL};
5232
5233 XML_SetUserData(g_parser, &test_data);
5234 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5235 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
5236 XML_SetEntityDeclHandler(g_parser, param_entity_match_handler);
5237 entity_name_to_match = XCS(PARAM_ENTITY_NAME);
5238 entity_value_to_match = XCS(PARAM_ENTITY_CORE_VALUE) XCS("\n");
5239 entity_match_flag = ENTITY_MATCH_NOT_FOUND;
5240 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5241 == XML_STATUS_ERROR)
5242 xml_failure(g_parser);
5243 if (entity_match_flag == ENTITY_MATCH_FAIL)
5244 fail("Parameter entity CR->NEWLINE conversion failed");
5245 else if (entity_match_flag == ENTITY_MATCH_NOT_FOUND)
5246 fail("Parameter entity not parsed");
5247 }
5248 #undef PARAM_ENTITY_NAME
5249 #undef PARAM_ENTITY_CORE_VALUE
5250 END_TEST
5251
START_TEST(test_invalid_character_entity)5252 START_TEST(test_invalid_character_entity) {
5253 const char *text = "<!DOCTYPE doc [\n"
5254 " <!ENTITY entity '�'>\n"
5255 "]>\n"
5256 "<doc>&entity;</doc>";
5257
5258 expect_failure(text, XML_ERROR_BAD_CHAR_REF,
5259 "Out of range character reference not faulted");
5260 }
5261 END_TEST
5262
START_TEST(test_invalid_character_entity_2)5263 START_TEST(test_invalid_character_entity_2) {
5264 const char *text = "<!DOCTYPE doc [\n"
5265 " <!ENTITY entity '&#xg0;'>\n"
5266 "]>\n"
5267 "<doc>&entity;</doc>";
5268
5269 expect_failure(text, XML_ERROR_INVALID_TOKEN,
5270 "Out of range character reference not faulted");
5271 }
5272 END_TEST
5273
START_TEST(test_invalid_character_entity_3)5274 START_TEST(test_invalid_character_entity_3) {
5275 const char text[] =
5276 /* <!DOCTYPE doc [\n */
5277 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0\n"
5278 /* U+0E04 = KHO KHWAI
5279 * U+0E08 = CHO CHAN */
5280 /* <!ENTITY entity '&\u0e04\u0e08;'>\n */
5281 "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0e\0n\0t\0i\0t\0y\0 "
5282 "\0'\0&\x0e\x04\x0e\x08\0;\0'\0>\0\n"
5283 /* ]>\n */
5284 "\0]\0>\0\n"
5285 /* <doc>&entity;</doc> */
5286 "\0<\0d\0o\0c\0>\0&\0e\0n\0t\0i\0t\0y\0;\0<\0/\0d\0o\0c\0>";
5287
5288 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5289 != XML_STATUS_ERROR)
5290 fail("Invalid start of entity name not faulted");
5291 if (XML_GetErrorCode(g_parser) != XML_ERROR_UNDEFINED_ENTITY)
5292 xml_failure(g_parser);
5293 }
5294 END_TEST
5295
START_TEST(test_invalid_character_entity_4)5296 START_TEST(test_invalid_character_entity_4) {
5297 const char *text = "<!DOCTYPE doc [\n"
5298 " <!ENTITY entity '�'>\n" /* = � */
5299 "]>\n"
5300 "<doc>&entity;</doc>";
5301
5302 expect_failure(text, XML_ERROR_BAD_CHAR_REF,
5303 "Out of range character reference not faulted");
5304 }
5305 END_TEST
5306
5307 /* Test that processing instructions are picked up by a default handler */
START_TEST(test_pi_handled_in_default)5308 START_TEST(test_pi_handled_in_default) {
5309 const char *text = "<?test processing instruction?>\n<doc/>";
5310 const XML_Char *expected = XCS("<?test processing instruction?>\n<doc/>");
5311 CharData storage;
5312
5313 CharData_Init(&storage);
5314 XML_SetDefaultHandler(g_parser, accumulate_characters);
5315 XML_SetUserData(g_parser, &storage);
5316 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5317 == XML_STATUS_ERROR)
5318 xml_failure(g_parser);
5319 CharData_CheckXMLChars(&storage, expected);
5320 }
5321 END_TEST
5322
5323 /* Test that comments are picked up by a default handler */
START_TEST(test_comment_handled_in_default)5324 START_TEST(test_comment_handled_in_default) {
5325 const char *text = "<!-- This is a comment -->\n<doc/>";
5326 const XML_Char *expected = XCS("<!-- This is a comment -->\n<doc/>");
5327 CharData storage;
5328
5329 CharData_Init(&storage);
5330 XML_SetDefaultHandler(g_parser, accumulate_characters);
5331 XML_SetUserData(g_parser, &storage);
5332 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5333 == XML_STATUS_ERROR)
5334 xml_failure(g_parser);
5335 CharData_CheckXMLChars(&storage, expected);
5336 }
5337 END_TEST
5338
5339 /* Test PIs that look almost but not quite like XML declarations */
5340 static void XMLCALL
accumulate_pi_characters(void * userData,const XML_Char * target,const XML_Char * data)5341 accumulate_pi_characters(void *userData, const XML_Char *target,
5342 const XML_Char *data) {
5343 CharData *storage = (CharData *)userData;
5344
5345 CharData_AppendXMLChars(storage, target, -1);
5346 CharData_AppendXMLChars(storage, XCS(": "), 2);
5347 CharData_AppendXMLChars(storage, data, -1);
5348 CharData_AppendXMLChars(storage, XCS("\n"), 1);
5349 }
5350
START_TEST(test_pi_yml)5351 START_TEST(test_pi_yml) {
5352 const char *text = "<?yml something like data?><doc/>";
5353 const XML_Char *expected = XCS("yml: something like data\n");
5354 CharData storage;
5355
5356 CharData_Init(&storage);
5357 XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5358 XML_SetUserData(g_parser, &storage);
5359 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5360 == XML_STATUS_ERROR)
5361 xml_failure(g_parser);
5362 CharData_CheckXMLChars(&storage, expected);
5363 }
5364 END_TEST
5365
START_TEST(test_pi_xnl)5366 START_TEST(test_pi_xnl) {
5367 const char *text = "<?xnl nothing like data?><doc/>";
5368 const XML_Char *expected = XCS("xnl: nothing like data\n");
5369 CharData storage;
5370
5371 CharData_Init(&storage);
5372 XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5373 XML_SetUserData(g_parser, &storage);
5374 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5375 == XML_STATUS_ERROR)
5376 xml_failure(g_parser);
5377 CharData_CheckXMLChars(&storage, expected);
5378 }
5379 END_TEST
5380
START_TEST(test_pi_xmm)5381 START_TEST(test_pi_xmm) {
5382 const char *text = "<?xmm everything like data?><doc/>";
5383 const XML_Char *expected = XCS("xmm: everything like data\n");
5384 CharData storage;
5385
5386 CharData_Init(&storage);
5387 XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5388 XML_SetUserData(g_parser, &storage);
5389 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5390 == XML_STATUS_ERROR)
5391 xml_failure(g_parser);
5392 CharData_CheckXMLChars(&storage, expected);
5393 }
5394 END_TEST
5395
START_TEST(test_utf16_pi)5396 START_TEST(test_utf16_pi) {
5397 const char text[] =
5398 /* <?{KHO KHWAI}{CHO CHAN}?>
5399 * where {KHO KHWAI} = U+0E04
5400 * and {CHO CHAN} = U+0E08
5401 */
5402 "<\0?\0\x04\x0e\x08\x0e?\0>\0"
5403 /* <q/> */
5404 "<\0q\0/\0>\0";
5405 #ifdef XML_UNICODE
5406 const XML_Char *expected = XCS("\x0e04\x0e08: \n");
5407 #else
5408 const XML_Char *expected = XCS("\xe0\xb8\x84\xe0\xb8\x88: \n");
5409 #endif
5410 CharData storage;
5411
5412 CharData_Init(&storage);
5413 XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5414 XML_SetUserData(g_parser, &storage);
5415 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5416 == XML_STATUS_ERROR)
5417 xml_failure(g_parser);
5418 CharData_CheckXMLChars(&storage, expected);
5419 }
5420 END_TEST
5421
START_TEST(test_utf16_be_pi)5422 START_TEST(test_utf16_be_pi) {
5423 const char text[] =
5424 /* <?{KHO KHWAI}{CHO CHAN}?>
5425 * where {KHO KHWAI} = U+0E04
5426 * and {CHO CHAN} = U+0E08
5427 */
5428 "\0<\0?\x0e\x04\x0e\x08\0?\0>"
5429 /* <q/> */
5430 "\0<\0q\0/\0>";
5431 #ifdef XML_UNICODE
5432 const XML_Char *expected = XCS("\x0e04\x0e08: \n");
5433 #else
5434 const XML_Char *expected = XCS("\xe0\xb8\x84\xe0\xb8\x88: \n");
5435 #endif
5436 CharData storage;
5437
5438 CharData_Init(&storage);
5439 XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5440 XML_SetUserData(g_parser, &storage);
5441 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5442 == XML_STATUS_ERROR)
5443 xml_failure(g_parser);
5444 CharData_CheckXMLChars(&storage, expected);
5445 }
5446 END_TEST
5447
5448 /* Test that comments can be picked up and translated */
5449 static void XMLCALL
accumulate_comment(void * userData,const XML_Char * data)5450 accumulate_comment(void *userData, const XML_Char *data) {
5451 CharData *storage = (CharData *)userData;
5452
5453 CharData_AppendXMLChars(storage, data, -1);
5454 }
5455
START_TEST(test_utf16_be_comment)5456 START_TEST(test_utf16_be_comment) {
5457 const char text[] =
5458 /* <!-- Comment A --> */
5459 "\0<\0!\0-\0-\0 \0C\0o\0m\0m\0e\0n\0t\0 \0A\0 \0-\0-\0>\0\n"
5460 /* <doc/> */
5461 "\0<\0d\0o\0c\0/\0>";
5462 const XML_Char *expected = XCS(" Comment A ");
5463 CharData storage;
5464
5465 CharData_Init(&storage);
5466 XML_SetCommentHandler(g_parser, accumulate_comment);
5467 XML_SetUserData(g_parser, &storage);
5468 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5469 == XML_STATUS_ERROR)
5470 xml_failure(g_parser);
5471 CharData_CheckXMLChars(&storage, expected);
5472 }
5473 END_TEST
5474
START_TEST(test_utf16_le_comment)5475 START_TEST(test_utf16_le_comment) {
5476 const char text[] =
5477 /* <!-- Comment B --> */
5478 "<\0!\0-\0-\0 \0C\0o\0m\0m\0e\0n\0t\0 \0B\0 \0-\0-\0>\0\n\0"
5479 /* <doc/> */
5480 "<\0d\0o\0c\0/\0>\0";
5481 const XML_Char *expected = XCS(" Comment B ");
5482 CharData storage;
5483
5484 CharData_Init(&storage);
5485 XML_SetCommentHandler(g_parser, accumulate_comment);
5486 XML_SetUserData(g_parser, &storage);
5487 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5488 == XML_STATUS_ERROR)
5489 xml_failure(g_parser);
5490 CharData_CheckXMLChars(&storage, expected);
5491 }
5492 END_TEST
5493
5494 /* Test that the unknown encoding handler with map entries that expect
5495 * conversion but no conversion function is faulted
5496 */
5497 static int XMLCALL
failing_converter(void * data,const char * s)5498 failing_converter(void *data, const char *s) {
5499 UNUSED_P(data);
5500 UNUSED_P(s);
5501 /* Always claim to have failed */
5502 return -1;
5503 }
5504
5505 static int XMLCALL
prefix_converter(void * data,const char * s)5506 prefix_converter(void *data, const char *s) {
5507 UNUSED_P(data);
5508 /* If the first byte is 0xff, raise an error */
5509 if (s[0] == (char)-1)
5510 return -1;
5511 /* Just add the low bits of the first byte to the second */
5512 return (s[1] + (s[0] & 0x7f)) & 0x01ff;
5513 }
5514
5515 static int XMLCALL
MiscEncodingHandler(void * data,const XML_Char * encoding,XML_Encoding * info)5516 MiscEncodingHandler(void *data, const XML_Char *encoding, XML_Encoding *info) {
5517 int i;
5518 int high_map = -2; /* Assume a 2-byte sequence */
5519
5520 if (! xcstrcmp(encoding, XCS("invalid-9"))
5521 || ! xcstrcmp(encoding, XCS("ascii-like"))
5522 || ! xcstrcmp(encoding, XCS("invalid-len"))
5523 || ! xcstrcmp(encoding, XCS("invalid-a"))
5524 || ! xcstrcmp(encoding, XCS("invalid-surrogate"))
5525 || ! xcstrcmp(encoding, XCS("invalid-high")))
5526 high_map = -1;
5527
5528 for (i = 0; i < 128; ++i)
5529 info->map[i] = i;
5530 for (; i < 256; ++i)
5531 info->map[i] = high_map;
5532
5533 /* If required, put an invalid value in the ASCII entries */
5534 if (! xcstrcmp(encoding, XCS("invalid-9")))
5535 info->map[9] = 5;
5536 /* If required, have a top-bit set character starts a 5-byte sequence */
5537 if (! xcstrcmp(encoding, XCS("invalid-len")))
5538 info->map[0x81] = -5;
5539 /* If required, make a top-bit set character a valid ASCII character */
5540 if (! xcstrcmp(encoding, XCS("invalid-a")))
5541 info->map[0x82] = 'a';
5542 /* If required, give a top-bit set character a forbidden value,
5543 * what would otherwise be the first of a surrogate pair.
5544 */
5545 if (! xcstrcmp(encoding, XCS("invalid-surrogate")))
5546 info->map[0x83] = 0xd801;
5547 /* If required, give a top-bit set character too high a value */
5548 if (! xcstrcmp(encoding, XCS("invalid-high")))
5549 info->map[0x84] = 0x010101;
5550
5551 info->data = data;
5552 info->release = NULL;
5553 if (! xcstrcmp(encoding, XCS("failing-conv")))
5554 info->convert = failing_converter;
5555 else if (! xcstrcmp(encoding, XCS("prefix-conv")))
5556 info->convert = prefix_converter;
5557 else
5558 info->convert = NULL;
5559 return XML_STATUS_OK;
5560 }
5561
START_TEST(test_missing_encoding_conversion_fn)5562 START_TEST(test_missing_encoding_conversion_fn) {
5563 const char *text = "<?xml version='1.0' encoding='no-conv'?>\n"
5564 "<doc>\x81</doc>";
5565
5566 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5567 /* MiscEncodingHandler sets up an encoding with every top-bit-set
5568 * character introducing a two-byte sequence. For this, it
5569 * requires a convert function. The above function call doesn't
5570 * pass one through, so when BadEncodingHandler actually gets
5571 * called it should supply an invalid encoding.
5572 */
5573 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5574 "Encoding with missing convert() not faulted");
5575 }
5576 END_TEST
5577
START_TEST(test_failing_encoding_conversion_fn)5578 START_TEST(test_failing_encoding_conversion_fn) {
5579 const char *text = "<?xml version='1.0' encoding='failing-conv'?>\n"
5580 "<doc>\x81</doc>";
5581
5582 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5583 /* BadEncodingHandler sets up an encoding with every top-bit-set
5584 * character introducing a two-byte sequence. For this, it
5585 * requires a convert function. The above function call passes
5586 * one that insists all possible sequences are invalid anyway.
5587 */
5588 expect_failure(text, XML_ERROR_INVALID_TOKEN,
5589 "Encoding with failing convert() not faulted");
5590 }
5591 END_TEST
5592
5593 /* Test unknown encoding conversions */
START_TEST(test_unknown_encoding_success)5594 START_TEST(test_unknown_encoding_success) {
5595 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5596 /* Equivalent to <eoc>Hello, world</eoc> */
5597 "<\x81\x64\x80oc>Hello, world</\x81\x64\x80oc>";
5598
5599 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5600 run_character_check(text, XCS("Hello, world"));
5601 }
5602 END_TEST
5603
5604 /* Test bad name character in unknown encoding */
START_TEST(test_unknown_encoding_bad_name)5605 START_TEST(test_unknown_encoding_bad_name) {
5606 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5607 "<\xff\x64oc>Hello, world</\xff\x64oc>";
5608
5609 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5610 expect_failure(text, XML_ERROR_INVALID_TOKEN,
5611 "Bad name start in unknown encoding not faulted");
5612 }
5613 END_TEST
5614
5615 /* Test bad mid-name character in unknown encoding */
START_TEST(test_unknown_encoding_bad_name_2)5616 START_TEST(test_unknown_encoding_bad_name_2) {
5617 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5618 "<d\xffoc>Hello, world</d\xffoc>";
5619
5620 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5621 expect_failure(text, XML_ERROR_INVALID_TOKEN,
5622 "Bad name in unknown encoding not faulted");
5623 }
5624 END_TEST
5625
5626 /* Test element name that is long enough to fill the conversion buffer
5627 * in an unknown encoding, finishing with an encoded character.
5628 */
START_TEST(test_unknown_encoding_long_name_1)5629 START_TEST(test_unknown_encoding_long_name_1) {
5630 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5631 "<abcdefghabcdefghabcdefghijkl\x80m\x80n\x80o\x80p>"
5632 "Hi"
5633 "</abcdefghabcdefghabcdefghijkl\x80m\x80n\x80o\x80p>";
5634 const XML_Char *expected = XCS("abcdefghabcdefghabcdefghijklmnop");
5635 CharData storage;
5636
5637 CharData_Init(&storage);
5638 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5639 XML_SetStartElementHandler(g_parser, record_element_start_handler);
5640 XML_SetUserData(g_parser, &storage);
5641 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5642 == XML_STATUS_ERROR)
5643 xml_failure(g_parser);
5644 CharData_CheckXMLChars(&storage, expected);
5645 }
5646 END_TEST
5647
5648 /* Test element name that is long enough to fill the conversion buffer
5649 * in an unknown encoding, finishing with an simple character.
5650 */
START_TEST(test_unknown_encoding_long_name_2)5651 START_TEST(test_unknown_encoding_long_name_2) {
5652 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5653 "<abcdefghabcdefghabcdefghijklmnop>"
5654 "Hi"
5655 "</abcdefghabcdefghabcdefghijklmnop>";
5656 const XML_Char *expected = XCS("abcdefghabcdefghabcdefghijklmnop");
5657 CharData storage;
5658
5659 CharData_Init(&storage);
5660 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5661 XML_SetStartElementHandler(g_parser, record_element_start_handler);
5662 XML_SetUserData(g_parser, &storage);
5663 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5664 == XML_STATUS_ERROR)
5665 xml_failure(g_parser);
5666 CharData_CheckXMLChars(&storage, expected);
5667 }
5668 END_TEST
5669
START_TEST(test_invalid_unknown_encoding)5670 START_TEST(test_invalid_unknown_encoding) {
5671 const char *text = "<?xml version='1.0' encoding='invalid-9'?>\n"
5672 "<doc>Hello world</doc>";
5673
5674 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5675 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5676 "Invalid unknown encoding not faulted");
5677 }
5678 END_TEST
5679
START_TEST(test_unknown_ascii_encoding_ok)5680 START_TEST(test_unknown_ascii_encoding_ok) {
5681 const char *text = "<?xml version='1.0' encoding='ascii-like'?>\n"
5682 "<doc>Hello, world</doc>";
5683
5684 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5685 run_character_check(text, XCS("Hello, world"));
5686 }
5687 END_TEST
5688
START_TEST(test_unknown_ascii_encoding_fail)5689 START_TEST(test_unknown_ascii_encoding_fail) {
5690 const char *text = "<?xml version='1.0' encoding='ascii-like'?>\n"
5691 "<doc>Hello, \x80 world</doc>";
5692
5693 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5694 expect_failure(text, XML_ERROR_INVALID_TOKEN,
5695 "Invalid character not faulted");
5696 }
5697 END_TEST
5698
START_TEST(test_unknown_encoding_invalid_length)5699 START_TEST(test_unknown_encoding_invalid_length) {
5700 const char *text = "<?xml version='1.0' encoding='invalid-len'?>\n"
5701 "<doc>Hello, world</doc>";
5702
5703 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5704 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5705 "Invalid unknown encoding not faulted");
5706 }
5707 END_TEST
5708
START_TEST(test_unknown_encoding_invalid_topbit)5709 START_TEST(test_unknown_encoding_invalid_topbit) {
5710 const char *text = "<?xml version='1.0' encoding='invalid-a'?>\n"
5711 "<doc>Hello, world</doc>";
5712
5713 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5714 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5715 "Invalid unknown encoding not faulted");
5716 }
5717 END_TEST
5718
START_TEST(test_unknown_encoding_invalid_surrogate)5719 START_TEST(test_unknown_encoding_invalid_surrogate) {
5720 const char *text = "<?xml version='1.0' encoding='invalid-surrogate'?>\n"
5721 "<doc>Hello, \x82 world</doc>";
5722
5723 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5724 expect_failure(text, XML_ERROR_INVALID_TOKEN,
5725 "Invalid unknown encoding not faulted");
5726 }
5727 END_TEST
5728
START_TEST(test_unknown_encoding_invalid_high)5729 START_TEST(test_unknown_encoding_invalid_high) {
5730 const char *text = "<?xml version='1.0' encoding='invalid-high'?>\n"
5731 "<doc>Hello, world</doc>";
5732
5733 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5734 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5735 "Invalid unknown encoding not faulted");
5736 }
5737 END_TEST
5738
START_TEST(test_unknown_encoding_invalid_attr_value)5739 START_TEST(test_unknown_encoding_invalid_attr_value) {
5740 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5741 "<doc attr='\xff\x30'/>";
5742
5743 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5744 expect_failure(text, XML_ERROR_INVALID_TOKEN,
5745 "Invalid attribute valid not faulted");
5746 }
5747 END_TEST
5748
5749 /* Test an external entity parser set to use latin-1 detects UTF-16
5750 * BOMs correctly.
5751 */
5752 enum ee_parse_flags { EE_PARSE_NONE = 0x00, EE_PARSE_FULL_BUFFER = 0x01 };
5753
5754 typedef struct ExtTest2 {
5755 const char *parse_text;
5756 int parse_len;
5757 const XML_Char *encoding;
5758 CharData *storage;
5759 enum ee_parse_flags flags;
5760 } ExtTest2;
5761
5762 static int XMLCALL
external_entity_loader2(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)5763 external_entity_loader2(XML_Parser parser, const XML_Char *context,
5764 const XML_Char *base, const XML_Char *systemId,
5765 const XML_Char *publicId) {
5766 ExtTest2 *test_data = (ExtTest2 *)XML_GetUserData(parser);
5767 XML_Parser extparser;
5768
5769 UNUSED_P(base);
5770 UNUSED_P(systemId);
5771 UNUSED_P(publicId);
5772 extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
5773 if (extparser == NULL)
5774 fail("Coulr not create external entity parser");
5775 if (test_data->encoding != NULL) {
5776 if (! XML_SetEncoding(extparser, test_data->encoding))
5777 fail("XML_SetEncoding() ignored for external entity");
5778 }
5779 if (test_data->flags & EE_PARSE_FULL_BUFFER) {
5780 if (XML_Parse(extparser, test_data->parse_text, test_data->parse_len,
5781 XML_TRUE)
5782 == XML_STATUS_ERROR) {
5783 xml_failure(extparser);
5784 }
5785 } else if (_XML_Parse_SINGLE_BYTES(extparser, test_data->parse_text,
5786 test_data->parse_len, XML_TRUE)
5787 == XML_STATUS_ERROR) {
5788 xml_failure(extparser);
5789 }
5790
5791 XML_ParserFree(extparser);
5792 return XML_STATUS_OK;
5793 }
5794
5795 /* Test that UTF-16 BOM does not select UTF-16 given explicit encoding */
5796 static void XMLCALL
ext2_accumulate_characters(void * userData,const XML_Char * s,int len)5797 ext2_accumulate_characters(void *userData, const XML_Char *s, int len) {
5798 ExtTest2 *test_data = (ExtTest2 *)userData;
5799 accumulate_characters(test_data->storage, s, len);
5800 }
5801
START_TEST(test_ext_entity_latin1_utf16le_bom)5802 START_TEST(test_ext_entity_latin1_utf16le_bom) {
5803 const char *text = "<!DOCTYPE doc [\n"
5804 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5805 "]>\n"
5806 "<doc>&en;</doc>";
5807 ExtTest2 test_data
5808 = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */
5809 /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn,
5810 * 0x4c = L and 0x20 is a space
5811 */
5812 "\xff\xfe\x4c\x20", 4, XCS("iso-8859-1"), NULL, EE_PARSE_NONE};
5813 #ifdef XML_UNICODE
5814 const XML_Char *expected = XCS("\x00ff\x00feL ");
5815 #else
5816 /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */
5817 const XML_Char *expected = XCS("\xc3\xbf\xc3\xbeL ");
5818 #endif
5819 CharData storage;
5820
5821 CharData_Init(&storage);
5822 test_data.storage = &storage;
5823 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5824 XML_SetUserData(g_parser, &test_data);
5825 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5826 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5827 == XML_STATUS_ERROR)
5828 xml_failure(g_parser);
5829 CharData_CheckXMLChars(&storage, expected);
5830 }
5831 END_TEST
5832
START_TEST(test_ext_entity_latin1_utf16be_bom)5833 START_TEST(test_ext_entity_latin1_utf16be_bom) {
5834 const char *text = "<!DOCTYPE doc [\n"
5835 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5836 "]>\n"
5837 "<doc>&en;</doc>";
5838 ExtTest2 test_data
5839 = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */
5840 /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn,
5841 * 0x4c = L and 0x20 is a space
5842 */
5843 "\xfe\xff\x20\x4c", 4, XCS("iso-8859-1"), NULL, EE_PARSE_NONE};
5844 #ifdef XML_UNICODE
5845 const XML_Char *expected = XCS("\x00fe\x00ff L");
5846 #else
5847 /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */
5848 const XML_Char *expected = XCS("\xc3\xbe\xc3\xbf L");
5849 #endif
5850 CharData storage;
5851
5852 CharData_Init(&storage);
5853 test_data.storage = &storage;
5854 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5855 XML_SetUserData(g_parser, &test_data);
5856 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5857 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5858 == XML_STATUS_ERROR)
5859 xml_failure(g_parser);
5860 CharData_CheckXMLChars(&storage, expected);
5861 }
5862 END_TEST
5863
5864 /* Parsing the full buffer rather than a byte at a time makes a
5865 * difference to the encoding scanning code, so repeat the above tests
5866 * without breaking them down by byte.
5867 */
START_TEST(test_ext_entity_latin1_utf16le_bom2)5868 START_TEST(test_ext_entity_latin1_utf16le_bom2) {
5869 const char *text = "<!DOCTYPE doc [\n"
5870 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5871 "]>\n"
5872 "<doc>&en;</doc>";
5873 ExtTest2 test_data
5874 = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */
5875 /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn,
5876 * 0x4c = L and 0x20 is a space
5877 */
5878 "\xff\xfe\x4c\x20", 4, XCS("iso-8859-1"), NULL, EE_PARSE_FULL_BUFFER};
5879 #ifdef XML_UNICODE
5880 const XML_Char *expected = XCS("\x00ff\x00feL ");
5881 #else
5882 /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */
5883 const XML_Char *expected = XCS("\xc3\xbf\xc3\xbeL ");
5884 #endif
5885 CharData storage;
5886
5887 CharData_Init(&storage);
5888 test_data.storage = &storage;
5889 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5890 XML_SetUserData(g_parser, &test_data);
5891 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5892 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
5893 == XML_STATUS_ERROR)
5894 xml_failure(g_parser);
5895 CharData_CheckXMLChars(&storage, expected);
5896 }
5897 END_TEST
5898
START_TEST(test_ext_entity_latin1_utf16be_bom2)5899 START_TEST(test_ext_entity_latin1_utf16be_bom2) {
5900 const char *text = "<!DOCTYPE doc [\n"
5901 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5902 "]>\n"
5903 "<doc>&en;</doc>";
5904 ExtTest2 test_data
5905 = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */
5906 /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn,
5907 * 0x4c = L and 0x20 is a space
5908 */
5909 "\xfe\xff\x20\x4c", 4, XCS("iso-8859-1"), NULL, EE_PARSE_FULL_BUFFER};
5910 #ifdef XML_UNICODE
5911 const XML_Char *expected = XCS("\x00fe\x00ff L");
5912 #else
5913 /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */
5914 const XML_Char *expected = "\xc3\xbe\xc3\xbf L";
5915 #endif
5916 CharData storage;
5917
5918 CharData_Init(&storage);
5919 test_data.storage = &storage;
5920 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5921 XML_SetUserData(g_parser, &test_data);
5922 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5923 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
5924 == XML_STATUS_ERROR)
5925 xml_failure(g_parser);
5926 CharData_CheckXMLChars(&storage, expected);
5927 }
5928 END_TEST
5929
5930 /* Test little-endian UTF-16 given an explicit big-endian encoding */
START_TEST(test_ext_entity_utf16_be)5931 START_TEST(test_ext_entity_utf16_be) {
5932 const char *text = "<!DOCTYPE doc [\n"
5933 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5934 "]>\n"
5935 "<doc>&en;</doc>";
5936 ExtTest2 test_data
5937 = {"<\0e\0/\0>\0", 8, XCS("utf-16be"), NULL, EE_PARSE_NONE};
5938 #ifdef XML_UNICODE
5939 const XML_Char *expected = XCS("\x3c00\x6500\x2f00\x3e00");
5940 #else
5941 const XML_Char *expected = XCS("\xe3\xb0\x80" /* U+3C00 */
5942 "\xe6\x94\x80" /* U+6500 */
5943 "\xe2\xbc\x80" /* U+2F00 */
5944 "\xe3\xb8\x80"); /* U+3E00 */
5945 #endif
5946 CharData storage;
5947
5948 CharData_Init(&storage);
5949 test_data.storage = &storage;
5950 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5951 XML_SetUserData(g_parser, &test_data);
5952 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5953 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5954 == XML_STATUS_ERROR)
5955 xml_failure(g_parser);
5956 CharData_CheckXMLChars(&storage, expected);
5957 }
5958 END_TEST
5959
5960 /* Test big-endian UTF-16 given an explicit little-endian encoding */
START_TEST(test_ext_entity_utf16_le)5961 START_TEST(test_ext_entity_utf16_le) {
5962 const char *text = "<!DOCTYPE doc [\n"
5963 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5964 "]>\n"
5965 "<doc>&en;</doc>";
5966 ExtTest2 test_data
5967 = {"\0<\0e\0/\0>", 8, XCS("utf-16le"), NULL, EE_PARSE_NONE};
5968 #ifdef XML_UNICODE
5969 const XML_Char *expected = XCS("\x3c00\x6500\x2f00\x3e00");
5970 #else
5971 const XML_Char *expected = XCS("\xe3\xb0\x80" /* U+3C00 */
5972 "\xe6\x94\x80" /* U+6500 */
5973 "\xe2\xbc\x80" /* U+2F00 */
5974 "\xe3\xb8\x80"); /* U+3E00 */
5975 #endif
5976 CharData storage;
5977
5978 CharData_Init(&storage);
5979 test_data.storage = &storage;
5980 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5981 XML_SetUserData(g_parser, &test_data);
5982 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5983 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5984 == XML_STATUS_ERROR)
5985 xml_failure(g_parser);
5986 CharData_CheckXMLChars(&storage, expected);
5987 }
5988 END_TEST
5989
5990 /* Test little-endian UTF-16 given no explicit encoding.
5991 * The existing default encoding (UTF-8) is assumed to hold without a
5992 * BOM to contradict it, so the entity value will in fact provoke an
5993 * error because 0x00 is not a valid XML character. We parse the
5994 * whole buffer in one go rather than feeding it in byte by byte to
5995 * exercise different code paths in the initial scanning routines.
5996 */
5997 typedef struct ExtFaults2 {
5998 const char *parse_text;
5999 int parse_len;
6000 const char *fail_text;
6001 const XML_Char *encoding;
6002 enum XML_Error error;
6003 } ExtFaults2;
6004
6005 static int XMLCALL
external_entity_faulter2(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)6006 external_entity_faulter2(XML_Parser parser, const XML_Char *context,
6007 const XML_Char *base, const XML_Char *systemId,
6008 const XML_Char *publicId) {
6009 ExtFaults2 *test_data = (ExtFaults2 *)XML_GetUserData(parser);
6010 XML_Parser extparser;
6011
6012 UNUSED_P(base);
6013 UNUSED_P(systemId);
6014 UNUSED_P(publicId);
6015 extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
6016 if (extparser == NULL)
6017 fail("Could not create external entity parser");
6018 if (test_data->encoding != NULL) {
6019 if (! XML_SetEncoding(extparser, test_data->encoding))
6020 fail("XML_SetEncoding() ignored for external entity");
6021 }
6022 if (XML_Parse(extparser, test_data->parse_text, test_data->parse_len,
6023 XML_TRUE)
6024 != XML_STATUS_ERROR)
6025 fail(test_data->fail_text);
6026 if (XML_GetErrorCode(extparser) != test_data->error)
6027 xml_failure(extparser);
6028
6029 XML_ParserFree(extparser);
6030 return XML_STATUS_ERROR;
6031 }
6032
START_TEST(test_ext_entity_utf16_unknown)6033 START_TEST(test_ext_entity_utf16_unknown) {
6034 const char *text = "<!DOCTYPE doc [\n"
6035 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
6036 "]>\n"
6037 "<doc>&en;</doc>";
6038 ExtFaults2 test_data
6039 = {"a\0b\0c\0", 6, "Invalid character in entity not faulted", NULL,
6040 XML_ERROR_INVALID_TOKEN};
6041
6042 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter2);
6043 XML_SetUserData(g_parser, &test_data);
6044 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
6045 "Invalid character should not have been accepted");
6046 }
6047 END_TEST
6048
6049 /* Test not-quite-UTF-8 BOM (0xEF 0xBB 0xBF) */
START_TEST(test_ext_entity_utf8_non_bom)6050 START_TEST(test_ext_entity_utf8_non_bom) {
6051 const char *text = "<!DOCTYPE doc [\n"
6052 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
6053 "]>\n"
6054 "<doc>&en;</doc>";
6055 ExtTest2 test_data
6056 = {"\xef\xbb\x80", /* Arabic letter DAD medial form, U+FEC0 */
6057 3, NULL, NULL, EE_PARSE_NONE};
6058 #ifdef XML_UNICODE
6059 const XML_Char *expected = XCS("\xfec0");
6060 #else
6061 const XML_Char *expected = XCS("\xef\xbb\x80");
6062 #endif
6063 CharData storage;
6064
6065 CharData_Init(&storage);
6066 test_data.storage = &storage;
6067 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
6068 XML_SetUserData(g_parser, &test_data);
6069 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
6070 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6071 == XML_STATUS_ERROR)
6072 xml_failure(g_parser);
6073 CharData_CheckXMLChars(&storage, expected);
6074 }
6075 END_TEST
6076
6077 /* Test that UTF-8 in a CDATA section is correctly passed through */
START_TEST(test_utf8_in_cdata_section)6078 START_TEST(test_utf8_in_cdata_section) {
6079 const char *text = "<doc><![CDATA[one \xc3\xa9 two]]></doc>";
6080 #ifdef XML_UNICODE
6081 const XML_Char *expected = XCS("one \x00e9 two");
6082 #else
6083 const XML_Char *expected = XCS("one \xc3\xa9 two");
6084 #endif
6085
6086 run_character_check(text, expected);
6087 }
6088 END_TEST
6089
6090 /* Test that little-endian UTF-16 in a CDATA section is handled */
START_TEST(test_utf8_in_cdata_section_2)6091 START_TEST(test_utf8_in_cdata_section_2) {
6092 const char *text = "<doc><![CDATA[\xc3\xa9]\xc3\xa9two]]></doc>";
6093 #ifdef XML_UNICODE
6094 const XML_Char *expected = XCS("\x00e9]\x00e9two");
6095 #else
6096 const XML_Char *expected = XCS("\xc3\xa9]\xc3\xa9two");
6097 #endif
6098
6099 run_character_check(text, expected);
6100 }
6101 END_TEST
6102
6103 /* Test trailing spaces in elements are accepted */
6104 static void XMLCALL
record_element_end_handler(void * userData,const XML_Char * name)6105 record_element_end_handler(void *userData, const XML_Char *name) {
6106 CharData *storage = (CharData *)userData;
6107
6108 CharData_AppendXMLChars(storage, XCS("/"), 1);
6109 CharData_AppendXMLChars(storage, name, -1);
6110 }
6111
START_TEST(test_trailing_spaces_in_elements)6112 START_TEST(test_trailing_spaces_in_elements) {
6113 const char *text = "<doc >Hi</doc >";
6114 const XML_Char *expected = XCS("doc/doc");
6115 CharData storage;
6116
6117 CharData_Init(&storage);
6118 XML_SetElementHandler(g_parser, record_element_start_handler,
6119 record_element_end_handler);
6120 XML_SetUserData(g_parser, &storage);
6121 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6122 == XML_STATUS_ERROR)
6123 xml_failure(g_parser);
6124 CharData_CheckXMLChars(&storage, expected);
6125 }
6126 END_TEST
6127
START_TEST(test_utf16_attribute)6128 START_TEST(test_utf16_attribute) {
6129 const char text[] =
6130 /* <d {KHO KHWAI}{CHO CHAN}='a'/>
6131 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
6132 * and {CHO CHAN} = U+0E08 = 0xe0 0xb8 0x88 in UTF-8
6133 */
6134 "<\0d\0 \0\x04\x0e\x08\x0e=\0'\0a\0'\0/\0>\0";
6135 const XML_Char *expected = XCS("a");
6136 CharData storage;
6137
6138 CharData_Init(&storage);
6139 XML_SetStartElementHandler(g_parser, accumulate_attribute);
6140 XML_SetUserData(g_parser, &storage);
6141 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6142 == XML_STATUS_ERROR)
6143 xml_failure(g_parser);
6144 CharData_CheckXMLChars(&storage, expected);
6145 }
6146 END_TEST
6147
START_TEST(test_utf16_second_attr)6148 START_TEST(test_utf16_second_attr) {
6149 /* <d a='1' {KHO KHWAI}{CHO CHAN}='2'/>
6150 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
6151 * and {CHO CHAN} = U+0E08 = 0xe0 0xb8 0x88 in UTF-8
6152 */
6153 const char text[] = "<\0d\0 \0a\0=\0'\0\x31\0'\0 \0"
6154 "\x04\x0e\x08\x0e=\0'\0\x32\0'\0/\0>\0";
6155 const XML_Char *expected = XCS("1");
6156 CharData storage;
6157
6158 CharData_Init(&storage);
6159 XML_SetStartElementHandler(g_parser, accumulate_attribute);
6160 XML_SetUserData(g_parser, &storage);
6161 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6162 == XML_STATUS_ERROR)
6163 xml_failure(g_parser);
6164 CharData_CheckXMLChars(&storage, expected);
6165 }
6166 END_TEST
6167
START_TEST(test_attr_after_solidus)6168 START_TEST(test_attr_after_solidus) {
6169 const char *text = "<doc attr1='a' / attr2='b'>";
6170
6171 expect_failure(text, XML_ERROR_INVALID_TOKEN, "Misplaced / not faulted");
6172 }
6173 END_TEST
6174
6175 static void XMLCALL
accumulate_entity_decl(void * userData,const XML_Char * entityName,int is_parameter_entity,const XML_Char * value,int value_length,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId,const XML_Char * notationName)6176 accumulate_entity_decl(void *userData, const XML_Char *entityName,
6177 int is_parameter_entity, const XML_Char *value,
6178 int value_length, const XML_Char *base,
6179 const XML_Char *systemId, const XML_Char *publicId,
6180 const XML_Char *notationName) {
6181 CharData *storage = (CharData *)userData;
6182
6183 UNUSED_P(is_parameter_entity);
6184 UNUSED_P(base);
6185 UNUSED_P(systemId);
6186 UNUSED_P(publicId);
6187 UNUSED_P(notationName);
6188 CharData_AppendXMLChars(storage, entityName, -1);
6189 CharData_AppendXMLChars(storage, XCS("="), 1);
6190 CharData_AppendXMLChars(storage, value, value_length);
6191 CharData_AppendXMLChars(storage, XCS("\n"), 1);
6192 }
6193
START_TEST(test_utf16_pe)6194 START_TEST(test_utf16_pe) {
6195 /* <!DOCTYPE doc [
6196 * <!ENTITY % {KHO KHWAI}{CHO CHAN} '<!ELEMENT doc (#PCDATA)>'>
6197 * %{KHO KHWAI}{CHO CHAN};
6198 * ]>
6199 * <doc></doc>
6200 *
6201 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
6202 * and {CHO CHAN} = U+0E08 = 0xe0 0xb8 0x88 in UTF-8
6203 */
6204 const char text[] = "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0\n"
6205 "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \x0e\x04\x0e\x08\0 "
6206 "\0'\0<\0!\0E\0L\0E\0M\0E\0N\0T\0 "
6207 "\0d\0o\0c\0 \0(\0#\0P\0C\0D\0A\0T\0A\0)\0>\0'\0>\0\n"
6208 "\0%\x0e\x04\x0e\x08\0;\0\n"
6209 "\0]\0>\0\n"
6210 "\0<\0d\0o\0c\0>\0<\0/\0d\0o\0c\0>";
6211 #ifdef XML_UNICODE
6212 const XML_Char *expected = XCS("\x0e04\x0e08=<!ELEMENT doc (#PCDATA)>\n");
6213 #else
6214 const XML_Char *expected
6215 = XCS("\xe0\xb8\x84\xe0\xb8\x88=<!ELEMENT doc (#PCDATA)>\n");
6216 #endif
6217 CharData storage;
6218
6219 CharData_Init(&storage);
6220 XML_SetUserData(g_parser, &storage);
6221 XML_SetEntityDeclHandler(g_parser, accumulate_entity_decl);
6222 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6223 == XML_STATUS_ERROR)
6224 xml_failure(g_parser);
6225 CharData_CheckXMLChars(&storage, expected);
6226 }
6227 END_TEST
6228
6229 /* Test that duff attribute description keywords are rejected */
START_TEST(test_bad_attr_desc_keyword)6230 START_TEST(test_bad_attr_desc_keyword) {
6231 const char *text = "<!DOCTYPE doc [\n"
6232 " <!ATTLIST doc attr CDATA #!IMPLIED>\n"
6233 "]>\n"
6234 "<doc />";
6235
6236 expect_failure(text, XML_ERROR_INVALID_TOKEN,
6237 "Bad keyword !IMPLIED not faulted");
6238 }
6239 END_TEST
6240
6241 /* Test that an invalid attribute description keyword consisting of
6242 * UTF-16 characters with their top bytes non-zero are correctly
6243 * faulted
6244 */
START_TEST(test_bad_attr_desc_keyword_utf16)6245 START_TEST(test_bad_attr_desc_keyword_utf16) {
6246 /* <!DOCTYPE d [
6247 * <!ATTLIST d a CDATA #{KHO KHWAI}{CHO CHAN}>
6248 * ]><d/>
6249 *
6250 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
6251 * and {CHO CHAN} = U+0E08 = 0xe0 0xb8 0x88 in UTF-8
6252 */
6253 const char text[]
6254 = "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n"
6255 "\0<\0!\0A\0T\0T\0L\0I\0S\0T\0 \0d\0 \0a\0 \0C\0D\0A\0T\0A\0 "
6256 "\0#\x0e\x04\x0e\x08\0>\0\n"
6257 "\0]\0>\0<\0d\0/\0>";
6258
6259 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6260 != XML_STATUS_ERROR)
6261 fail("Invalid UTF16 attribute keyword not faulted");
6262 if (XML_GetErrorCode(g_parser) != XML_ERROR_SYNTAX)
6263 xml_failure(g_parser);
6264 }
6265 END_TEST
6266
6267 /* Test that invalid syntax in a <!DOCTYPE> is rejected. Do this
6268 * using prefix-encoding (see above) to trigger specific code paths
6269 */
START_TEST(test_bad_doctype)6270 START_TEST(test_bad_doctype) {
6271 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
6272 "<!DOCTYPE doc [ \x80\x44 ]><doc/>";
6273
6274 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
6275 expect_failure(text, XML_ERROR_SYNTAX,
6276 "Invalid bytes in DOCTYPE not faulted");
6277 }
6278 END_TEST
6279
START_TEST(test_bad_doctype_utf16)6280 START_TEST(test_bad_doctype_utf16) {
6281 const char text[] =
6282 /* <!DOCTYPE doc [ \x06f2 ]><doc/>
6283 *
6284 * U+06F2 = EXTENDED ARABIC-INDIC DIGIT TWO, a valid number
6285 * (name character) but not a valid letter (name start character)
6286 */
6287 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0 "
6288 "\x06\xf2"
6289 "\0 \0]\0>\0<\0d\0o\0c\0/\0>";
6290
6291 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6292 != XML_STATUS_ERROR)
6293 fail("Invalid bytes in DOCTYPE not faulted");
6294 if (XML_GetErrorCode(g_parser) != XML_ERROR_SYNTAX)
6295 xml_failure(g_parser);
6296 }
6297 END_TEST
6298
START_TEST(test_bad_doctype_plus)6299 START_TEST(test_bad_doctype_plus) {
6300 const char *text = "<!DOCTYPE 1+ [ <!ENTITY foo 'bar'> ]>\n"
6301 "<1+>&foo;</1+>";
6302
6303 expect_failure(text, XML_ERROR_INVALID_TOKEN,
6304 "'+' in document name not faulted");
6305 }
6306 END_TEST
6307
START_TEST(test_bad_doctype_star)6308 START_TEST(test_bad_doctype_star) {
6309 const char *text = "<!DOCTYPE 1* [ <!ENTITY foo 'bar'> ]>\n"
6310 "<1*>&foo;</1*>";
6311
6312 expect_failure(text, XML_ERROR_INVALID_TOKEN,
6313 "'*' in document name not faulted");
6314 }
6315 END_TEST
6316
START_TEST(test_bad_doctype_query)6317 START_TEST(test_bad_doctype_query) {
6318 const char *text = "<!DOCTYPE 1? [ <!ENTITY foo 'bar'> ]>\n"
6319 "<1?>&foo;</1?>";
6320
6321 expect_failure(text, XML_ERROR_INVALID_TOKEN,
6322 "'?' in document name not faulted");
6323 }
6324 END_TEST
6325
START_TEST(test_unknown_encoding_bad_ignore)6326 START_TEST(test_unknown_encoding_bad_ignore) {
6327 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>"
6328 "<!DOCTYPE doc SYSTEM 'foo'>"
6329 "<doc><e>&entity;</e></doc>";
6330 ExtFaults fault = {"<![IGNORE[<!ELEMENT \xffG (#PCDATA)*>]]>",
6331 "Invalid character not faulted", XCS("prefix-conv"),
6332 XML_ERROR_INVALID_TOKEN};
6333
6334 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
6335 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6336 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
6337 XML_SetUserData(g_parser, &fault);
6338 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
6339 "Bad IGNORE section with unknown encoding not failed");
6340 }
6341 END_TEST
6342
START_TEST(test_entity_in_utf16_be_attr)6343 START_TEST(test_entity_in_utf16_be_attr) {
6344 const char text[] =
6345 /* <e a='ä ä'></e> */
6346 "\0<\0e\0 \0a\0=\0'\0&\0#\0\x32\0\x32\0\x38\0;\0 "
6347 "\0&\0#\0x\0\x30\0\x30\0E\0\x34\0;\0'\0>\0<\0/\0e\0>";
6348 #ifdef XML_UNICODE
6349 const XML_Char *expected = XCS("\x00e4 \x00e4");
6350 #else
6351 const XML_Char *expected = XCS("\xc3\xa4 \xc3\xa4");
6352 #endif
6353 CharData storage;
6354
6355 CharData_Init(&storage);
6356 XML_SetUserData(g_parser, &storage);
6357 XML_SetStartElementHandler(g_parser, accumulate_attribute);
6358 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6359 == XML_STATUS_ERROR)
6360 xml_failure(g_parser);
6361 CharData_CheckXMLChars(&storage, expected);
6362 }
6363 END_TEST
6364
START_TEST(test_entity_in_utf16_le_attr)6365 START_TEST(test_entity_in_utf16_le_attr) {
6366 const char text[] =
6367 /* <e a='ä ä'></e> */
6368 "<\0e\0 \0a\0=\0'\0&\0#\0\x32\0\x32\0\x38\0;\0 \0"
6369 "&\0#\0x\0\x30\0\x30\0E\0\x34\0;\0'\0>\0<\0/\0e\0>\0";
6370 #ifdef XML_UNICODE
6371 const XML_Char *expected = XCS("\x00e4 \x00e4");
6372 #else
6373 const XML_Char *expected = XCS("\xc3\xa4 \xc3\xa4");
6374 #endif
6375 CharData storage;
6376
6377 CharData_Init(&storage);
6378 XML_SetUserData(g_parser, &storage);
6379 XML_SetStartElementHandler(g_parser, accumulate_attribute);
6380 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6381 == XML_STATUS_ERROR)
6382 xml_failure(g_parser);
6383 CharData_CheckXMLChars(&storage, expected);
6384 }
6385 END_TEST
6386
START_TEST(test_entity_public_utf16_be)6387 START_TEST(test_entity_public_utf16_be) {
6388 const char text[] =
6389 /* <!DOCTYPE d [ */
6390 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n"
6391 /* <!ENTITY % e PUBLIC 'foo' 'bar.ent'> */
6392 "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \0e\0 \0P\0U\0B\0L\0I\0C\0 "
6393 "\0'\0f\0o\0o\0'\0 \0'\0b\0a\0r\0.\0e\0n\0t\0'\0>\0\n"
6394 /* %e; */
6395 "\0%\0e\0;\0\n"
6396 /* ]> */
6397 "\0]\0>\0\n"
6398 /* <d>&j;</d> */
6399 "\0<\0d\0>\0&\0j\0;\0<\0/\0d\0>";
6400 ExtTest2 test_data = {/* <!ENTITY j 'baz'> */
6401 "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0j\0 \0'\0b\0a\0z\0'\0>",
6402 34, NULL, NULL, EE_PARSE_NONE};
6403 const XML_Char *expected = XCS("baz");
6404 CharData storage;
6405
6406 CharData_Init(&storage);
6407 test_data.storage = &storage;
6408 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6409 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
6410 XML_SetUserData(g_parser, &test_data);
6411 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
6412 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6413 == XML_STATUS_ERROR)
6414 xml_failure(g_parser);
6415 CharData_CheckXMLChars(&storage, expected);
6416 }
6417 END_TEST
6418
START_TEST(test_entity_public_utf16_le)6419 START_TEST(test_entity_public_utf16_le) {
6420 const char text[] =
6421 /* <!DOCTYPE d [ */
6422 "<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n\0"
6423 /* <!ENTITY % e PUBLIC 'foo' 'bar.ent'> */
6424 "<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \0e\0 \0P\0U\0B\0L\0I\0C\0 \0"
6425 "'\0f\0o\0o\0'\0 \0'\0b\0a\0r\0.\0e\0n\0t\0'\0>\0\n\0"
6426 /* %e; */
6427 "%\0e\0;\0\n\0"
6428 /* ]> */
6429 "]\0>\0\n\0"
6430 /* <d>&j;</d> */
6431 "<\0d\0>\0&\0j\0;\0<\0/\0d\0>\0";
6432 ExtTest2 test_data = {/* <!ENTITY j 'baz'> */
6433 "<\0!\0E\0N\0T\0I\0T\0Y\0 \0j\0 \0'\0b\0a\0z\0'\0>\0",
6434 34, NULL, NULL, EE_PARSE_NONE};
6435 const XML_Char *expected = XCS("baz");
6436 CharData storage;
6437
6438 CharData_Init(&storage);
6439 test_data.storage = &storage;
6440 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6441 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
6442 XML_SetUserData(g_parser, &test_data);
6443 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
6444 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6445 == XML_STATUS_ERROR)
6446 xml_failure(g_parser);
6447 CharData_CheckXMLChars(&storage, expected);
6448 }
6449 END_TEST
6450
6451 /* Test that a doctype with neither an internal nor external subset is
6452 * faulted
6453 */
START_TEST(test_short_doctype)6454 START_TEST(test_short_doctype) {
6455 const char *text = "<!DOCTYPE doc></doc>";
6456 expect_failure(text, XML_ERROR_INVALID_TOKEN,
6457 "DOCTYPE without subset not rejected");
6458 }
6459 END_TEST
6460
START_TEST(test_short_doctype_2)6461 START_TEST(test_short_doctype_2) {
6462 const char *text = "<!DOCTYPE doc PUBLIC></doc>";
6463 expect_failure(text, XML_ERROR_SYNTAX,
6464 "DOCTYPE without Public ID not rejected");
6465 }
6466 END_TEST
6467
START_TEST(test_short_doctype_3)6468 START_TEST(test_short_doctype_3) {
6469 const char *text = "<!DOCTYPE doc SYSTEM></doc>";
6470 expect_failure(text, XML_ERROR_SYNTAX,
6471 "DOCTYPE without System ID not rejected");
6472 }
6473 END_TEST
6474
START_TEST(test_long_doctype)6475 START_TEST(test_long_doctype) {
6476 const char *text = "<!DOCTYPE doc PUBLIC 'foo' 'bar' 'baz'></doc>";
6477 expect_failure(text, XML_ERROR_SYNTAX, "DOCTYPE with extra ID not rejected");
6478 }
6479 END_TEST
6480
START_TEST(test_bad_entity)6481 START_TEST(test_bad_entity) {
6482 const char *text = "<!DOCTYPE doc [\n"
6483 " <!ENTITY foo PUBLIC>\n"
6484 "]>\n"
6485 "<doc/>";
6486 expect_failure(text, XML_ERROR_SYNTAX,
6487 "ENTITY without Public ID is not rejected");
6488 }
6489 END_TEST
6490
6491 /* Test unquoted value is faulted */
START_TEST(test_bad_entity_2)6492 START_TEST(test_bad_entity_2) {
6493 const char *text = "<!DOCTYPE doc [\n"
6494 " <!ENTITY % foo bar>\n"
6495 "]>\n"
6496 "<doc/>";
6497 expect_failure(text, XML_ERROR_SYNTAX,
6498 "ENTITY without Public ID is not rejected");
6499 }
6500 END_TEST
6501
START_TEST(test_bad_entity_3)6502 START_TEST(test_bad_entity_3) {
6503 const char *text = "<!DOCTYPE doc [\n"
6504 " <!ENTITY % foo PUBLIC>\n"
6505 "]>\n"
6506 "<doc/>";
6507 expect_failure(text, XML_ERROR_SYNTAX,
6508 "Parameter ENTITY without Public ID is not rejected");
6509 }
6510 END_TEST
6511
START_TEST(test_bad_entity_4)6512 START_TEST(test_bad_entity_4) {
6513 const char *text = "<!DOCTYPE doc [\n"
6514 " <!ENTITY % foo SYSTEM>\n"
6515 "]>\n"
6516 "<doc/>";
6517 expect_failure(text, XML_ERROR_SYNTAX,
6518 "Parameter ENTITY without Public ID is not rejected");
6519 }
6520 END_TEST
6521
START_TEST(test_bad_notation)6522 START_TEST(test_bad_notation) {
6523 const char *text = "<!DOCTYPE doc [\n"
6524 " <!NOTATION n SYSTEM>\n"
6525 "]>\n"
6526 "<doc/>";
6527 expect_failure(text, XML_ERROR_SYNTAX,
6528 "Notation without System ID is not rejected");
6529 }
6530 END_TEST
6531
6532 /* Test for issue #11, wrongly suppressed default handler */
6533 typedef struct default_check {
6534 const XML_Char *expected;
6535 const int expectedLen;
6536 XML_Bool seen;
6537 } DefaultCheck;
6538
6539 static void XMLCALL
checking_default_handler(void * userData,const XML_Char * s,int len)6540 checking_default_handler(void *userData, const XML_Char *s, int len) {
6541 DefaultCheck *data = (DefaultCheck *)userData;
6542 int i;
6543
6544 for (i = 0; data[i].expected != NULL; i++) {
6545 if (data[i].expectedLen == len
6546 && ! memcmp(data[i].expected, s, len * sizeof(XML_Char))) {
6547 data[i].seen = XML_TRUE;
6548 break;
6549 }
6550 }
6551 }
6552
START_TEST(test_default_doctype_handler)6553 START_TEST(test_default_doctype_handler) {
6554 const char *text = "<!DOCTYPE doc PUBLIC 'pubname' 'test.dtd' [\n"
6555 " <!ENTITY foo 'bar'>\n"
6556 "]>\n"
6557 "<doc>&foo;</doc>";
6558 DefaultCheck test_data[] = {{XCS("'pubname'"), 9, XML_FALSE},
6559 {XCS("'test.dtd'"), 10, XML_FALSE},
6560 {NULL, 0, XML_FALSE}};
6561 int i;
6562
6563 XML_SetUserData(g_parser, &test_data);
6564 XML_SetDefaultHandler(g_parser, checking_default_handler);
6565 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
6566 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6567 == XML_STATUS_ERROR)
6568 xml_failure(g_parser);
6569 for (i = 0; test_data[i].expected != NULL; i++)
6570 if (! test_data[i].seen)
6571 fail("Default handler not run for public !DOCTYPE");
6572 }
6573 END_TEST
6574
START_TEST(test_empty_element_abort)6575 START_TEST(test_empty_element_abort) {
6576 const char *text = "<abort/>";
6577
6578 XML_SetStartElementHandler(g_parser, start_element_suspender);
6579 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6580 != XML_STATUS_ERROR)
6581 fail("Expected to error on abort");
6582 }
6583 END_TEST
6584
6585 /*
6586 * Namespaces tests.
6587 */
6588
6589 static void
namespace_setup(void)6590 namespace_setup(void) {
6591 g_parser = XML_ParserCreateNS(NULL, XCS(' '));
6592 if (g_parser == NULL)
6593 fail("Parser not created.");
6594 }
6595
6596 static void
namespace_teardown(void)6597 namespace_teardown(void) {
6598 basic_teardown();
6599 }
6600
6601 /* Check that an element name and attribute name match the expected values.
6602 The expected values are passed as an array reference of string pointers
6603 provided as the userData argument; the first is the expected
6604 element name, and the second is the expected attribute name.
6605 */
6606 static int triplet_start_flag = XML_FALSE;
6607 static int triplet_end_flag = XML_FALSE;
6608
6609 static void XMLCALL
triplet_start_checker(void * userData,const XML_Char * name,const XML_Char ** atts)6610 triplet_start_checker(void *userData, const XML_Char *name,
6611 const XML_Char **atts) {
6612 XML_Char **elemstr = (XML_Char **)userData;
6613 char buffer[1024];
6614 if (xcstrcmp(elemstr[0], name) != 0) {
6615 sprintf(buffer, "unexpected start string: '%" XML_FMT_STR "'", name);
6616 fail(buffer);
6617 }
6618 if (xcstrcmp(elemstr[1], atts[0]) != 0) {
6619 sprintf(buffer, "unexpected attribute string: '%" XML_FMT_STR "'", atts[0]);
6620 fail(buffer);
6621 }
6622 triplet_start_flag = XML_TRUE;
6623 }
6624
6625 /* Check that the element name passed to the end-element handler matches
6626 the expected value. The expected value is passed as the first element
6627 in an array of strings passed as the userData argument.
6628 */
6629 static void XMLCALL
triplet_end_checker(void * userData,const XML_Char * name)6630 triplet_end_checker(void *userData, const XML_Char *name) {
6631 XML_Char **elemstr = (XML_Char **)userData;
6632 if (xcstrcmp(elemstr[0], name) != 0) {
6633 char buffer[1024];
6634 sprintf(buffer, "unexpected end string: '%" XML_FMT_STR "'", name);
6635 fail(buffer);
6636 }
6637 triplet_end_flag = XML_TRUE;
6638 }
6639
START_TEST(test_return_ns_triplet)6640 START_TEST(test_return_ns_triplet) {
6641 const char *text = "<foo:e xmlns:foo='http://example.org/' bar:a='12'\n"
6642 " xmlns:bar='http://example.org/'>";
6643 const char *epilog = "</foo:e>";
6644 const XML_Char *elemstr[]
6645 = {XCS("http://example.org/ e foo"), XCS("http://example.org/ a bar")};
6646 XML_SetReturnNSTriplet(g_parser, XML_TRUE);
6647 XML_SetUserData(g_parser, (void *)elemstr);
6648 XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
6649 XML_SetNamespaceDeclHandler(g_parser, dummy_start_namespace_decl_handler,
6650 dummy_end_namespace_decl_handler);
6651 triplet_start_flag = XML_FALSE;
6652 triplet_end_flag = XML_FALSE;
6653 dummy_handler_flags = 0;
6654 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
6655 == XML_STATUS_ERROR)
6656 xml_failure(g_parser);
6657 if (! triplet_start_flag)
6658 fail("triplet_start_checker not invoked");
6659 /* Check that unsetting "return triplets" fails while still parsing */
6660 XML_SetReturnNSTriplet(g_parser, XML_FALSE);
6661 if (_XML_Parse_SINGLE_BYTES(g_parser, epilog, (int)strlen(epilog), XML_TRUE)
6662 == XML_STATUS_ERROR)
6663 xml_failure(g_parser);
6664 if (! triplet_end_flag)
6665 fail("triplet_end_checker not invoked");
6666 if (dummy_handler_flags
6667 != (DUMMY_START_NS_DECL_HANDLER_FLAG | DUMMY_END_NS_DECL_HANDLER_FLAG))
6668 fail("Namespace handlers not called");
6669 }
6670 END_TEST
6671
6672 static void XMLCALL
overwrite_start_checker(void * userData,const XML_Char * name,const XML_Char ** atts)6673 overwrite_start_checker(void *userData, const XML_Char *name,
6674 const XML_Char **atts) {
6675 CharData *storage = (CharData *)userData;
6676 CharData_AppendXMLChars(storage, XCS("start "), 6);
6677 CharData_AppendXMLChars(storage, name, -1);
6678 while (*atts != NULL) {
6679 CharData_AppendXMLChars(storage, XCS("\nattribute "), 11);
6680 CharData_AppendXMLChars(storage, *atts, -1);
6681 atts += 2;
6682 }
6683 CharData_AppendXMLChars(storage, XCS("\n"), 1);
6684 }
6685
6686 static void XMLCALL
overwrite_end_checker(void * userData,const XML_Char * name)6687 overwrite_end_checker(void *userData, const XML_Char *name) {
6688 CharData *storage = (CharData *)userData;
6689 CharData_AppendXMLChars(storage, XCS("end "), 4);
6690 CharData_AppendXMLChars(storage, name, -1);
6691 CharData_AppendXMLChars(storage, XCS("\n"), 1);
6692 }
6693
6694 static void
run_ns_tagname_overwrite_test(const char * text,const XML_Char * result)6695 run_ns_tagname_overwrite_test(const char *text, const XML_Char *result) {
6696 CharData storage;
6697 CharData_Init(&storage);
6698 XML_SetUserData(g_parser, &storage);
6699 XML_SetElementHandler(g_parser, overwrite_start_checker,
6700 overwrite_end_checker);
6701 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6702 == XML_STATUS_ERROR)
6703 xml_failure(g_parser);
6704 CharData_CheckXMLChars(&storage, result);
6705 }
6706
6707 /* Regression test for SF bug #566334. */
START_TEST(test_ns_tagname_overwrite)6708 START_TEST(test_ns_tagname_overwrite) {
6709 const char *text = "<n:e xmlns:n='http://example.org/'>\n"
6710 " <n:f n:attr='foo'/>\n"
6711 " <n:g n:attr2='bar'/>\n"
6712 "</n:e>";
6713 const XML_Char *result = XCS("start http://example.org/ e\n")
6714 XCS("start http://example.org/ f\n")
6715 XCS("attribute http://example.org/ attr\n")
6716 XCS("end http://example.org/ f\n")
6717 XCS("start http://example.org/ g\n")
6718 XCS("attribute http://example.org/ attr2\n")
6719 XCS("end http://example.org/ g\n")
6720 XCS("end http://example.org/ e\n");
6721 run_ns_tagname_overwrite_test(text, result);
6722 }
6723 END_TEST
6724
6725 /* Regression test for SF bug #566334. */
START_TEST(test_ns_tagname_overwrite_triplet)6726 START_TEST(test_ns_tagname_overwrite_triplet) {
6727 const char *text = "<n:e xmlns:n='http://example.org/'>\n"
6728 " <n:f n:attr='foo'/>\n"
6729 " <n:g n:attr2='bar'/>\n"
6730 "</n:e>";
6731 const XML_Char *result = XCS("start http://example.org/ e n\n")
6732 XCS("start http://example.org/ f n\n")
6733 XCS("attribute http://example.org/ attr n\n")
6734 XCS("end http://example.org/ f n\n")
6735 XCS("start http://example.org/ g n\n")
6736 XCS("attribute http://example.org/ attr2 n\n")
6737 XCS("end http://example.org/ g n\n")
6738 XCS("end http://example.org/ e n\n");
6739 XML_SetReturnNSTriplet(g_parser, XML_TRUE);
6740 run_ns_tagname_overwrite_test(text, result);
6741 }
6742 END_TEST
6743
6744 /* Regression test for SF bug #620343. */
6745 static void XMLCALL
start_element_fail(void * userData,const XML_Char * name,const XML_Char ** atts)6746 start_element_fail(void *userData, const XML_Char *name,
6747 const XML_Char **atts) {
6748 UNUSED_P(userData);
6749 UNUSED_P(name);
6750 UNUSED_P(atts);
6751
6752 /* We should never get here. */
6753 fail("should never reach start_element_fail()");
6754 }
6755
6756 static void XMLCALL
start_ns_clearing_start_element(void * userData,const XML_Char * prefix,const XML_Char * uri)6757 start_ns_clearing_start_element(void *userData, const XML_Char *prefix,
6758 const XML_Char *uri) {
6759 UNUSED_P(prefix);
6760 UNUSED_P(uri);
6761 XML_SetStartElementHandler((XML_Parser)userData, NULL);
6762 }
6763
START_TEST(test_start_ns_clears_start_element)6764 START_TEST(test_start_ns_clears_start_element) {
6765 /* This needs to use separate start/end tags; using the empty tag
6766 syntax doesn't cause the problematic path through Expat to be
6767 taken.
6768 */
6769 const char *text = "<e xmlns='http://example.org/'></e>";
6770
6771 XML_SetStartElementHandler(g_parser, start_element_fail);
6772 XML_SetStartNamespaceDeclHandler(g_parser, start_ns_clearing_start_element);
6773 XML_SetEndNamespaceDeclHandler(g_parser, dummy_end_namespace_decl_handler);
6774 XML_UseParserAsHandlerArg(g_parser);
6775 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6776 == XML_STATUS_ERROR)
6777 xml_failure(g_parser);
6778 }
6779 END_TEST
6780
6781 /* Regression test for SF bug #616863. */
6782 static int XMLCALL
external_entity_handler(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)6783 external_entity_handler(XML_Parser parser, const XML_Char *context,
6784 const XML_Char *base, const XML_Char *systemId,
6785 const XML_Char *publicId) {
6786 intptr_t callno = 1 + (intptr_t)XML_GetUserData(parser);
6787 const char *text;
6788 XML_Parser p2;
6789
6790 UNUSED_P(base);
6791 UNUSED_P(systemId);
6792 UNUSED_P(publicId);
6793 if (callno == 1)
6794 text = ("<!ELEMENT doc (e+)>\n"
6795 "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
6796 "<!ELEMENT e EMPTY>\n");
6797 else
6798 text = ("<?xml version='1.0' encoding='us-ascii'?>"
6799 "<e/>");
6800
6801 XML_SetUserData(parser, (void *)callno);
6802 p2 = XML_ExternalEntityParserCreate(parser, context, NULL);
6803 if (_XML_Parse_SINGLE_BYTES(p2, text, (int)strlen(text), XML_TRUE)
6804 == XML_STATUS_ERROR) {
6805 xml_failure(p2);
6806 return XML_STATUS_ERROR;
6807 }
6808 XML_ParserFree(p2);
6809 return XML_STATUS_OK;
6810 }
6811
START_TEST(test_default_ns_from_ext_subset_and_ext_ge)6812 START_TEST(test_default_ns_from_ext_subset_and_ext_ge) {
6813 const char *text = "<?xml version='1.0'?>\n"
6814 "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n"
6815 " <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n"
6816 "]>\n"
6817 "<doc xmlns='http://example.org/ns1'>\n"
6818 "&en;\n"
6819 "</doc>";
6820
6821 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6822 XML_SetExternalEntityRefHandler(g_parser, external_entity_handler);
6823 /* We actually need to set this handler to tickle this bug. */
6824 XML_SetStartElementHandler(g_parser, dummy_start_element);
6825 XML_SetUserData(g_parser, NULL);
6826 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6827 == XML_STATUS_ERROR)
6828 xml_failure(g_parser);
6829 }
6830 END_TEST
6831
6832 /* Regression test #1 for SF bug #673791. */
START_TEST(test_ns_prefix_with_empty_uri_1)6833 START_TEST(test_ns_prefix_with_empty_uri_1) {
6834 const char *text = "<doc xmlns:prefix='http://example.org/'>\n"
6835 " <e xmlns:prefix=''/>\n"
6836 "</doc>";
6837
6838 expect_failure(text, XML_ERROR_UNDECLARING_PREFIX,
6839 "Did not report re-setting namespace"
6840 " URI with prefix to ''.");
6841 }
6842 END_TEST
6843
6844 /* Regression test #2 for SF bug #673791. */
START_TEST(test_ns_prefix_with_empty_uri_2)6845 START_TEST(test_ns_prefix_with_empty_uri_2) {
6846 const char *text = "<?xml version='1.0'?>\n"
6847 "<docelem xmlns:pre=''/>";
6848
6849 expect_failure(text, XML_ERROR_UNDECLARING_PREFIX,
6850 "Did not report setting namespace URI with prefix to ''.");
6851 }
6852 END_TEST
6853
6854 /* Regression test #3 for SF bug #673791. */
START_TEST(test_ns_prefix_with_empty_uri_3)6855 START_TEST(test_ns_prefix_with_empty_uri_3) {
6856 const char *text = "<!DOCTYPE doc [\n"
6857 " <!ELEMENT doc EMPTY>\n"
6858 " <!ATTLIST doc\n"
6859 " xmlns:prefix CDATA ''>\n"
6860 "]>\n"
6861 "<doc/>";
6862
6863 expect_failure(text, XML_ERROR_UNDECLARING_PREFIX,
6864 "Didn't report attr default setting NS w/ prefix to ''.");
6865 }
6866 END_TEST
6867
6868 /* Regression test #4 for SF bug #673791. */
START_TEST(test_ns_prefix_with_empty_uri_4)6869 START_TEST(test_ns_prefix_with_empty_uri_4) {
6870 const char *text = "<!DOCTYPE doc [\n"
6871 " <!ELEMENT prefix:doc EMPTY>\n"
6872 " <!ATTLIST prefix:doc\n"
6873 " xmlns:prefix CDATA 'http://example.org/'>\n"
6874 "]>\n"
6875 "<prefix:doc/>";
6876 /* Packaged info expected by the end element handler;
6877 the weird structuring lets us re-use the triplet_end_checker()
6878 function also used for another test. */
6879 const XML_Char *elemstr[] = {XCS("http://example.org/ doc prefix")};
6880 XML_SetReturnNSTriplet(g_parser, XML_TRUE);
6881 XML_SetUserData(g_parser, (void *)elemstr);
6882 XML_SetEndElementHandler(g_parser, triplet_end_checker);
6883 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6884 == XML_STATUS_ERROR)
6885 xml_failure(g_parser);
6886 }
6887 END_TEST
6888
6889 /* Test with non-xmlns prefix */
START_TEST(test_ns_unbound_prefix)6890 START_TEST(test_ns_unbound_prefix) {
6891 const char *text = "<!DOCTYPE doc [\n"
6892 " <!ELEMENT prefix:doc EMPTY>\n"
6893 " <!ATTLIST prefix:doc\n"
6894 " notxmlns:prefix CDATA 'http://example.org/'>\n"
6895 "]>\n"
6896 "<prefix:doc/>";
6897
6898 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6899 != XML_STATUS_ERROR)
6900 fail("Unbound prefix incorrectly passed");
6901 if (XML_GetErrorCode(g_parser) != XML_ERROR_UNBOUND_PREFIX)
6902 xml_failure(g_parser);
6903 }
6904 END_TEST
6905
START_TEST(test_ns_default_with_empty_uri)6906 START_TEST(test_ns_default_with_empty_uri) {
6907 const char *text = "<doc xmlns='http://example.org/'>\n"
6908 " <e xmlns=''/>\n"
6909 "</doc>";
6910 /* Add some handlers to exercise extra code paths */
6911 XML_SetStartNamespaceDeclHandler(g_parser,
6912 dummy_start_namespace_decl_handler);
6913 XML_SetEndNamespaceDeclHandler(g_parser, dummy_end_namespace_decl_handler);
6914 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6915 == XML_STATUS_ERROR)
6916 xml_failure(g_parser);
6917 }
6918 END_TEST
6919
6920 /* Regression test for SF bug #692964: two prefixes for one namespace. */
START_TEST(test_ns_duplicate_attrs_diff_prefixes)6921 START_TEST(test_ns_duplicate_attrs_diff_prefixes) {
6922 const char *text = "<doc xmlns:a='http://example.org/a'\n"
6923 " xmlns:b='http://example.org/a'\n"
6924 " a:a='v' b:a='v' />";
6925 expect_failure(text, XML_ERROR_DUPLICATE_ATTRIBUTE,
6926 "did not report multiple attributes with same URI+name");
6927 }
6928 END_TEST
6929
START_TEST(test_ns_duplicate_hashes)6930 START_TEST(test_ns_duplicate_hashes) {
6931 /* The hash of an attribute is calculated as the hash of its URI
6932 * concatenated with a space followed by its name (after the
6933 * colon). We wish to generate attributes with the same hash
6934 * value modulo the attribute table size so that we can check that
6935 * the attribute hash table works correctly. The attribute hash
6936 * table size will be the smallest power of two greater than the
6937 * number of attributes, but at least eight. There is
6938 * unfortunately no programmatic way of getting the hash or the
6939 * table size at user level, but the test code coverage percentage
6940 * will drop if the hashes cease to point to the same row.
6941 *
6942 * The cunning plan is to have few enough attributes to have a
6943 * reliable table size of 8, and have the single letter attribute
6944 * names be 8 characters apart, producing a hash which will be the
6945 * same modulo 8.
6946 */
6947 const char *text = "<doc xmlns:a='http://example.org/a'\n"
6948 " a:a='v' a:i='w' />";
6949 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6950 == XML_STATUS_ERROR)
6951 xml_failure(g_parser);
6952 }
6953 END_TEST
6954
6955 /* Regression test for SF bug #695401: unbound prefix. */
START_TEST(test_ns_unbound_prefix_on_attribute)6956 START_TEST(test_ns_unbound_prefix_on_attribute) {
6957 const char *text = "<doc a:attr=''/>";
6958 expect_failure(text, XML_ERROR_UNBOUND_PREFIX,
6959 "did not report unbound prefix on attribute");
6960 }
6961 END_TEST
6962
6963 /* Regression test for SF bug #695401: unbound prefix. */
START_TEST(test_ns_unbound_prefix_on_element)6964 START_TEST(test_ns_unbound_prefix_on_element) {
6965 const char *text = "<a:doc/>";
6966 expect_failure(text, XML_ERROR_UNBOUND_PREFIX,
6967 "did not report unbound prefix on element");
6968 }
6969 END_TEST
6970
6971 /* Test that the parsing status is correctly reset by XML_ParserReset().
6972 * We usE test_return_ns_triplet() for our example parse to improve
6973 * coverage of tidying up code executed.
6974 */
START_TEST(test_ns_parser_reset)6975 START_TEST(test_ns_parser_reset) {
6976 XML_ParsingStatus status;
6977
6978 XML_GetParsingStatus(g_parser, &status);
6979 if (status.parsing != XML_INITIALIZED)
6980 fail("parsing status doesn't start INITIALIZED");
6981 test_return_ns_triplet();
6982 XML_GetParsingStatus(g_parser, &status);
6983 if (status.parsing != XML_FINISHED)
6984 fail("parsing status doesn't end FINISHED");
6985 XML_ParserReset(g_parser, NULL);
6986 XML_GetParsingStatus(g_parser, &status);
6987 if (status.parsing != XML_INITIALIZED)
6988 fail("parsing status doesn't reset to INITIALIZED");
6989 }
6990 END_TEST
6991
6992 /* Test that long element names with namespaces are handled correctly */
START_TEST(test_ns_long_element)6993 START_TEST(test_ns_long_element) {
6994 const char *text
6995 = "<foo:thisisalongenoughelementnametotriggerareallocation\n"
6996 " xmlns:foo='http://example.org/' bar:a='12'\n"
6997 " xmlns:bar='http://example.org/'>"
6998 "</foo:thisisalongenoughelementnametotriggerareallocation>";
6999 const XML_Char *elemstr[]
7000 = {XCS("http://example.org/")
7001 XCS(" thisisalongenoughelementnametotriggerareallocation foo"),
7002 XCS("http://example.org/ a bar")};
7003
7004 XML_SetReturnNSTriplet(g_parser, XML_TRUE);
7005 XML_SetUserData(g_parser, (void *)elemstr);
7006 XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
7007 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7008 == XML_STATUS_ERROR)
7009 xml_failure(g_parser);
7010 }
7011 END_TEST
7012
7013 /* Test mixed population of prefixed and unprefixed attributes */
START_TEST(test_ns_mixed_prefix_atts)7014 START_TEST(test_ns_mixed_prefix_atts) {
7015 const char *text = "<e a='12' bar:b='13'\n"
7016 " xmlns:bar='http://example.org/'>"
7017 "</e>";
7018
7019 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7020 == XML_STATUS_ERROR)
7021 xml_failure(g_parser);
7022 }
7023 END_TEST
7024
7025 /* Test having a long namespaced element name inside a short one.
7026 * This exercises some internal buffer reallocation that is shared
7027 * across elements with the same namespace URI.
7028 */
START_TEST(test_ns_extend_uri_buffer)7029 START_TEST(test_ns_extend_uri_buffer) {
7030 const char *text = "<foo:e xmlns:foo='http://example.org/'>"
7031 " <foo:thisisalongenoughnametotriggerallocationaction"
7032 " foo:a='12' />"
7033 "</foo:e>";
7034 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7035 == XML_STATUS_ERROR)
7036 xml_failure(g_parser);
7037 }
7038 END_TEST
7039
7040 /* Test that xmlns is correctly rejected as an attribute in the xmlns
7041 * namespace, but not in other namespaces
7042 */
START_TEST(test_ns_reserved_attributes)7043 START_TEST(test_ns_reserved_attributes) {
7044 const char *text1
7045 = "<foo:e xmlns:foo='http://example.org/' xmlns:xmlns='12' />";
7046 const char *text2
7047 = "<foo:e xmlns:foo='http://example.org/' foo:xmlns='12' />";
7048 expect_failure(text1, XML_ERROR_RESERVED_PREFIX_XMLNS,
7049 "xmlns not rejected as an attribute");
7050 XML_ParserReset(g_parser, NULL);
7051 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
7052 == XML_STATUS_ERROR)
7053 xml_failure(g_parser);
7054 }
7055 END_TEST
7056
7057 /* Test more reserved attributes */
START_TEST(test_ns_reserved_attributes_2)7058 START_TEST(test_ns_reserved_attributes_2) {
7059 const char *text1 = "<foo:e xmlns:foo='http://example.org/'"
7060 " xmlns:xml='http://example.org/' />";
7061 const char *text2
7062 = "<foo:e xmlns:foo='http://www.w3.org/XML/1998/namespace' />";
7063 const char *text3 = "<foo:e xmlns:foo='http://www.w3.org/2000/xmlns/' />";
7064
7065 expect_failure(text1, XML_ERROR_RESERVED_PREFIX_XML,
7066 "xml not rejected as an attribute");
7067 XML_ParserReset(g_parser, NULL);
7068 expect_failure(text2, XML_ERROR_RESERVED_NAMESPACE_URI,
7069 "Use of w3.org URL not faulted");
7070 XML_ParserReset(g_parser, NULL);
7071 expect_failure(text3, XML_ERROR_RESERVED_NAMESPACE_URI,
7072 "Use of w3.org xmlns URL not faulted");
7073 }
7074 END_TEST
7075
7076 /* Test string pool handling of namespace names of 2048 characters */
7077 /* Exercises a particular string pool growth path */
START_TEST(test_ns_extremely_long_prefix)7078 START_TEST(test_ns_extremely_long_prefix) {
7079 /* C99 compilers are only required to support 4095-character
7080 * strings, so the following needs to be split in two to be safe
7081 * for all compilers.
7082 */
7083 const char *text1
7084 = "<doc "
7085 /* 64 character on each line */
7086 /* ...gives a total length of 2048 */
7087 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7088 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7089 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7090 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7091 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7092 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7093 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7094 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7095 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7096 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7097 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7098 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7099 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7100 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7101 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7102 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7103 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7104 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7105 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7106 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7107 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7108 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7109 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7110 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7111 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7112 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7113 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7114 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7115 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7116 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7117 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7118 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7119 ":a='12'";
7120 const char *text2
7121 = " xmlns:"
7122 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7123 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7124 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7125 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7126 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7127 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7128 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7129 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7130 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7131 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7132 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7133 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7134 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7135 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7136 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7137 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7138 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7139 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7140 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7141 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7142 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7143 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7144 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7145 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7146 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7147 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7148 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7149 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7150 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7151 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7152 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7153 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7154 "='foo'\n>"
7155 "</doc>";
7156
7157 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
7158 == XML_STATUS_ERROR)
7159 xml_failure(g_parser);
7160 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
7161 == XML_STATUS_ERROR)
7162 xml_failure(g_parser);
7163 }
7164 END_TEST
7165
7166 /* Test unknown encoding handlers in namespace setup */
START_TEST(test_ns_unknown_encoding_success)7167 START_TEST(test_ns_unknown_encoding_success) {
7168 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
7169 "<foo:e xmlns:foo='http://example.org/'>Hi</foo:e>";
7170
7171 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
7172 run_character_check(text, XCS("Hi"));
7173 }
7174 END_TEST
7175
7176 /* Test that too many colons are rejected */
START_TEST(test_ns_double_colon)7177 START_TEST(test_ns_double_colon) {
7178 const char *text = "<foo:e xmlns:foo='http://example.org/' foo:a:b='bar' />";
7179 const enum XML_Status status
7180 = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE);
7181 #ifdef XML_NS
7182 if ((status == XML_STATUS_OK)
7183 || (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)) {
7184 fail("Double colon in attribute name not faulted"
7185 " (despite active namespace support)");
7186 }
7187 #else
7188 if (status != XML_STATUS_OK) {
7189 fail("Double colon in attribute name faulted"
7190 " (despite inactive namespace support");
7191 }
7192 #endif
7193 }
7194 END_TEST
7195
START_TEST(test_ns_double_colon_element)7196 START_TEST(test_ns_double_colon_element) {
7197 const char *text = "<foo:bar:e xmlns:foo='http://example.org/' />";
7198 const enum XML_Status status
7199 = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE);
7200 #ifdef XML_NS
7201 if ((status == XML_STATUS_OK)
7202 || (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)) {
7203 fail("Double colon in element name not faulted"
7204 " (despite active namespace support)");
7205 }
7206 #else
7207 if (status != XML_STATUS_OK) {
7208 fail("Double colon in element name faulted"
7209 " (despite inactive namespace support");
7210 }
7211 #endif
7212 }
7213 END_TEST
7214
7215 /* Test that non-name characters after a colon are rejected */
START_TEST(test_ns_bad_attr_leafname)7216 START_TEST(test_ns_bad_attr_leafname) {
7217 const char *text = "<foo:e xmlns:foo='http://example.org/' foo:?ar='baz' />";
7218
7219 expect_failure(text, XML_ERROR_INVALID_TOKEN,
7220 "Invalid character in leafname not faulted");
7221 }
7222 END_TEST
7223
START_TEST(test_ns_bad_element_leafname)7224 START_TEST(test_ns_bad_element_leafname) {
7225 const char *text = "<foo:?oc xmlns:foo='http://example.org/' />";
7226
7227 expect_failure(text, XML_ERROR_INVALID_TOKEN,
7228 "Invalid character in element leafname not faulted");
7229 }
7230 END_TEST
7231
7232 /* Test high-byte-set UTF-16 characters are valid in a leafname */
START_TEST(test_ns_utf16_leafname)7233 START_TEST(test_ns_utf16_leafname) {
7234 const char text[] =
7235 /* <n:e xmlns:n='URI' n:{KHO KHWAI}='a' />
7236 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
7237 */
7238 "<\0n\0:\0e\0 \0x\0m\0l\0n\0s\0:\0n\0=\0'\0U\0R\0I\0'\0 \0"
7239 "n\0:\0\x04\x0e=\0'\0a\0'\0 \0/\0>\0";
7240 const XML_Char *expected = XCS("a");
7241 CharData storage;
7242
7243 CharData_Init(&storage);
7244 XML_SetStartElementHandler(g_parser, accumulate_attribute);
7245 XML_SetUserData(g_parser, &storage);
7246 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
7247 == XML_STATUS_ERROR)
7248 xml_failure(g_parser);
7249 CharData_CheckXMLChars(&storage, expected);
7250 }
7251 END_TEST
7252
START_TEST(test_ns_utf16_element_leafname)7253 START_TEST(test_ns_utf16_element_leafname) {
7254 const char text[] =
7255 /* <n:{KHO KHWAI} xmlns:n='URI'/>
7256 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
7257 */
7258 "\0<\0n\0:\x0e\x04\0 \0x\0m\0l\0n\0s\0:\0n\0=\0'\0U\0R\0I\0'\0/\0>";
7259 #ifdef XML_UNICODE
7260 const XML_Char *expected = XCS("URI \x0e04");
7261 #else
7262 const XML_Char *expected = XCS("URI \xe0\xb8\x84");
7263 #endif
7264 CharData storage;
7265
7266 CharData_Init(&storage);
7267 XML_SetStartElementHandler(g_parser, start_element_event_handler);
7268 XML_SetUserData(g_parser, &storage);
7269 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
7270 == XML_STATUS_ERROR)
7271 xml_failure(g_parser);
7272 CharData_CheckXMLChars(&storage, expected);
7273 }
7274 END_TEST
7275
START_TEST(test_ns_utf16_doctype)7276 START_TEST(test_ns_utf16_doctype) {
7277 const char text[] =
7278 /* <!DOCTYPE foo:{KHO KHWAI} [ <!ENTITY bar 'baz'> ]>\n
7279 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
7280 */
7281 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0f\0o\0o\0:\x0e\x04\0 "
7282 "\0[\0 \0<\0!\0E\0N\0T\0I\0T\0Y\0 \0b\0a\0r\0 \0'\0b\0a\0z\0'\0>\0 "
7283 "\0]\0>\0\n"
7284 /* <foo:{KHO KHWAI} xmlns:foo='URI'>&bar;</foo:{KHO KHWAI}> */
7285 "\0<\0f\0o\0o\0:\x0e\x04\0 "
7286 "\0x\0m\0l\0n\0s\0:\0f\0o\0o\0=\0'\0U\0R\0I\0'\0>"
7287 "\0&\0b\0a\0r\0;"
7288 "\0<\0/\0f\0o\0o\0:\x0e\x04\0>";
7289 #ifdef XML_UNICODE
7290 const XML_Char *expected = XCS("URI \x0e04");
7291 #else
7292 const XML_Char *expected = XCS("URI \xe0\xb8\x84");
7293 #endif
7294 CharData storage;
7295
7296 CharData_Init(&storage);
7297 XML_SetUserData(g_parser, &storage);
7298 XML_SetStartElementHandler(g_parser, start_element_event_handler);
7299 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
7300 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
7301 == XML_STATUS_ERROR)
7302 xml_failure(g_parser);
7303 CharData_CheckXMLChars(&storage, expected);
7304 }
7305 END_TEST
7306
START_TEST(test_ns_invalid_doctype)7307 START_TEST(test_ns_invalid_doctype) {
7308 const char *text = "<!DOCTYPE foo:!bad [ <!ENTITY bar 'baz' ]>\n"
7309 "<foo:!bad>&bar;</foo:!bad>";
7310
7311 expect_failure(text, XML_ERROR_INVALID_TOKEN,
7312 "Invalid character in document local name not faulted");
7313 }
7314 END_TEST
7315
START_TEST(test_ns_double_colon_doctype)7316 START_TEST(test_ns_double_colon_doctype) {
7317 const char *text = "<!DOCTYPE foo:a:doc [ <!ENTITY bar 'baz' ]>\n"
7318 "<foo:a:doc>&bar;</foo:a:doc>";
7319
7320 expect_failure(text, XML_ERROR_SYNTAX,
7321 "Double colon in document name not faulted");
7322 }
7323 END_TEST
7324
7325 /* Control variable; the number of times duff_allocator() will successfully
7326 * allocate */
7327 #define ALLOC_ALWAYS_SUCCEED (-1)
7328 #define REALLOC_ALWAYS_SUCCEED (-1)
7329
7330 static intptr_t allocation_count = ALLOC_ALWAYS_SUCCEED;
7331 static intptr_t reallocation_count = REALLOC_ALWAYS_SUCCEED;
7332
7333 /* Crocked allocator for allocation failure tests */
7334 static void *
duff_allocator(size_t size)7335 duff_allocator(size_t size) {
7336 if (allocation_count == 0)
7337 return NULL;
7338 if (allocation_count != ALLOC_ALWAYS_SUCCEED)
7339 allocation_count--;
7340 return malloc(size);
7341 }
7342
7343 /* Crocked reallocator for allocation failure tests */
7344 static void *
duff_reallocator(void * ptr,size_t size)7345 duff_reallocator(void *ptr, size_t size) {
7346 if (reallocation_count == 0)
7347 return NULL;
7348 if (reallocation_count != REALLOC_ALWAYS_SUCCEED)
7349 reallocation_count--;
7350 return realloc(ptr, size);
7351 }
7352
7353 /* Test that a failure to allocate the parser structure fails gracefully */
START_TEST(test_misc_alloc_create_parser)7354 START_TEST(test_misc_alloc_create_parser) {
7355 XML_Memory_Handling_Suite memsuite = {duff_allocator, realloc, free};
7356 unsigned int i;
7357 const unsigned int max_alloc_count = 10;
7358
7359 /* Something this simple shouldn't need more than 10 allocations */
7360 for (i = 0; i < max_alloc_count; i++) {
7361 allocation_count = i;
7362 g_parser = XML_ParserCreate_MM(NULL, &memsuite, NULL);
7363 if (g_parser != NULL)
7364 break;
7365 }
7366 if (i == 0)
7367 fail("Parser unexpectedly ignored failing allocator");
7368 else if (i == max_alloc_count)
7369 fail("Parser not created with max allocation count");
7370 }
7371 END_TEST
7372
7373 /* Test memory allocation failures for a parser with an encoding */
START_TEST(test_misc_alloc_create_parser_with_encoding)7374 START_TEST(test_misc_alloc_create_parser_with_encoding) {
7375 XML_Memory_Handling_Suite memsuite = {duff_allocator, realloc, free};
7376 unsigned int i;
7377 const unsigned int max_alloc_count = 10;
7378
7379 /* Try several levels of allocation */
7380 for (i = 0; i < max_alloc_count; i++) {
7381 allocation_count = i;
7382 g_parser = XML_ParserCreate_MM(XCS("us-ascii"), &memsuite, NULL);
7383 if (g_parser != NULL)
7384 break;
7385 }
7386 if (i == 0)
7387 fail("Parser ignored failing allocator");
7388 else if (i == max_alloc_count)
7389 fail("Parser not created with max allocation count");
7390 }
7391 END_TEST
7392
7393 /* Test that freeing a NULL parser doesn't cause an explosion.
7394 * (Not actually tested anywhere else)
7395 */
START_TEST(test_misc_null_parser)7396 START_TEST(test_misc_null_parser) {
7397 XML_ParserFree(NULL);
7398 }
7399 END_TEST
7400
7401 /* Test that XML_ErrorString rejects out-of-range codes */
START_TEST(test_misc_error_string)7402 START_TEST(test_misc_error_string) {
7403 if (XML_ErrorString((enum XML_Error) - 1) != NULL)
7404 fail("Negative error code not rejected");
7405 if (XML_ErrorString((enum XML_Error)100) != NULL)
7406 fail("Large error code not rejected");
7407 }
7408 END_TEST
7409
7410 /* Test the version information is consistent */
7411
7412 /* Since we are working in XML_LChars (potentially 16-bits), we
7413 * can't use the standard C library functions for character
7414 * manipulation and have to roll our own.
7415 */
7416 static int
parse_version(const XML_LChar * version_text,XML_Expat_Version * version_struct)7417 parse_version(const XML_LChar *version_text,
7418 XML_Expat_Version *version_struct) {
7419 if (! version_text)
7420 return XML_FALSE;
7421
7422 while (*version_text != 0x00) {
7423 if (*version_text >= ASCII_0 && *version_text <= ASCII_9)
7424 break;
7425 version_text++;
7426 }
7427 if (*version_text == 0x00)
7428 return XML_FALSE;
7429
7430 /* version_struct->major = strtoul(version_text, 10, &version_text) */
7431 version_struct->major = 0;
7432 while (*version_text >= ASCII_0 && *version_text <= ASCII_9) {
7433 version_struct->major
7434 = 10 * version_struct->major + (*version_text++ - ASCII_0);
7435 }
7436 if (*version_text++ != ASCII_PERIOD)
7437 return XML_FALSE;
7438
7439 /* Now for the minor version number */
7440 version_struct->minor = 0;
7441 while (*version_text >= ASCII_0 && *version_text <= ASCII_9) {
7442 version_struct->minor
7443 = 10 * version_struct->minor + (*version_text++ - ASCII_0);
7444 }
7445 if (*version_text++ != ASCII_PERIOD)
7446 return XML_FALSE;
7447
7448 /* Finally the micro version number */
7449 version_struct->micro = 0;
7450 while (*version_text >= ASCII_0 && *version_text <= ASCII_9) {
7451 version_struct->micro
7452 = 10 * version_struct->micro + (*version_text++ - ASCII_0);
7453 }
7454 if (*version_text != 0x00)
7455 return XML_FALSE;
7456 return XML_TRUE;
7457 }
7458
7459 static int
versions_equal(const XML_Expat_Version * first,const XML_Expat_Version * second)7460 versions_equal(const XML_Expat_Version *first,
7461 const XML_Expat_Version *second) {
7462 return (first->major == second->major && first->minor == second->minor
7463 && first->micro == second->micro);
7464 }
7465
START_TEST(test_misc_version)7466 START_TEST(test_misc_version) {
7467 XML_Expat_Version read_version = XML_ExpatVersionInfo();
7468 /* Silence compiler warning with the following assignment */
7469 XML_Expat_Version parsed_version = {0, 0, 0};
7470 const XML_LChar *version_text = XML_ExpatVersion();
7471
7472 if (version_text == NULL)
7473 fail("Could not obtain version text");
7474 assert(version_text != NULL);
7475 if (! parse_version(version_text, &parsed_version))
7476 fail("Unable to parse version text");
7477 if (! versions_equal(&read_version, &parsed_version))
7478 fail("Version mismatch");
7479
7480 #if ! defined(XML_UNICODE) || defined(XML_UNICODE_WCHAR_T)
7481 if (xcstrcmp(version_text, XCS("expat_2.4.1"))) /* needs bump on releases */
7482 fail("XML_*_VERSION in expat.h out of sync?\n");
7483 #else
7484 /* If we have XML_UNICODE defined but not XML_UNICODE_WCHAR_T
7485 * then XML_LChar is defined as char, for some reason.
7486 */
7487 if (strcmp(version_text, "expat_2.2.5")) /* needs bump on releases */
7488 fail("XML_*_VERSION in expat.h out of sync?\n");
7489 #endif /* ! defined(XML_UNICODE) || defined(XML_UNICODE_WCHAR_T) */
7490 }
7491 END_TEST
7492
7493 /* Test feature information */
START_TEST(test_misc_features)7494 START_TEST(test_misc_features) {
7495 const XML_Feature *features = XML_GetFeatureList();
7496
7497 /* Prevent problems with double-freeing parsers */
7498 g_parser = NULL;
7499 if (features == NULL) {
7500 fail("Failed to get feature information");
7501 } else {
7502 /* Loop through the features checking what we can */
7503 while (features->feature != XML_FEATURE_END) {
7504 switch (features->feature) {
7505 case XML_FEATURE_SIZEOF_XML_CHAR:
7506 if (features->value != sizeof(XML_Char))
7507 fail("Incorrect size of XML_Char");
7508 break;
7509 case XML_FEATURE_SIZEOF_XML_LCHAR:
7510 if (features->value != sizeof(XML_LChar))
7511 fail("Incorrect size of XML_LChar");
7512 break;
7513 default:
7514 break;
7515 }
7516 features++;
7517 }
7518 }
7519 }
7520 END_TEST
7521
7522 /* Regression test for GitHub Issue #17: memory leak parsing attribute
7523 * values with mixed bound and unbound namespaces.
7524 */
START_TEST(test_misc_attribute_leak)7525 START_TEST(test_misc_attribute_leak) {
7526 const char *text = "<D xmlns:L=\"D\" l:a='' L:a=''/>";
7527 XML_Memory_Handling_Suite memsuite
7528 = {tracking_malloc, tracking_realloc, tracking_free};
7529
7530 g_parser = XML_ParserCreate_MM(XCS("UTF-8"), &memsuite, XCS("\n"));
7531 expect_failure(text, XML_ERROR_UNBOUND_PREFIX, "Unbound prefixes not found");
7532 XML_ParserFree(g_parser);
7533 /* Prevent the teardown trying to double free */
7534 g_parser = NULL;
7535
7536 if (! tracking_report())
7537 fail("Memory leak found");
7538 }
7539 END_TEST
7540
7541 /* Test parser created for UTF-16LE is successful */
START_TEST(test_misc_utf16le)7542 START_TEST(test_misc_utf16le) {
7543 const char text[] =
7544 /* <?xml version='1.0'?><q>Hi</q> */
7545 "<\0?\0x\0m\0l\0 \0"
7546 "v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0?\0>\0"
7547 "<\0q\0>\0H\0i\0<\0/\0q\0>\0";
7548 const XML_Char *expected = XCS("Hi");
7549 CharData storage;
7550
7551 g_parser = XML_ParserCreate(XCS("UTF-16LE"));
7552 if (g_parser == NULL)
7553 fail("Parser not created");
7554
7555 CharData_Init(&storage);
7556 XML_SetUserData(g_parser, &storage);
7557 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
7558 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
7559 == XML_STATUS_ERROR)
7560 xml_failure(g_parser);
7561 CharData_CheckXMLChars(&storage, expected);
7562 }
7563 END_TEST
7564
7565 typedef struct {
7566 XML_Parser parser;
7567 int deep;
7568 } DataIssue240;
7569
7570 static void
start_element_issue_240(void * userData,const XML_Char * name,const XML_Char ** atts)7571 start_element_issue_240(void *userData, const XML_Char *name,
7572 const XML_Char **atts) {
7573 DataIssue240 *mydata = (DataIssue240 *)userData;
7574 UNUSED_P(name);
7575 UNUSED_P(atts);
7576 mydata->deep++;
7577 }
7578
7579 static void
end_element_issue_240(void * userData,const XML_Char * name)7580 end_element_issue_240(void *userData, const XML_Char *name) {
7581 DataIssue240 *mydata = (DataIssue240 *)userData;
7582
7583 UNUSED_P(name);
7584 mydata->deep--;
7585 if (mydata->deep == 0) {
7586 XML_StopParser(mydata->parser, 0);
7587 }
7588 }
7589
START_TEST(test_misc_stop_during_end_handler_issue_240_1)7590 START_TEST(test_misc_stop_during_end_handler_issue_240_1) {
7591 XML_Parser parser;
7592 DataIssue240 *mydata;
7593 enum XML_Status result;
7594 const char *const doc1 = "<doc><e1/><e><foo/></e></doc>";
7595
7596 parser = XML_ParserCreate(NULL);
7597 XML_SetElementHandler(parser, start_element_issue_240, end_element_issue_240);
7598 mydata = (DataIssue240 *)malloc(sizeof(DataIssue240));
7599 mydata->parser = parser;
7600 mydata->deep = 0;
7601 XML_SetUserData(parser, mydata);
7602
7603 result = XML_Parse(parser, doc1, (int)strlen(doc1), 1);
7604 XML_ParserFree(parser);
7605 free(mydata);
7606 if (result != XML_STATUS_ERROR)
7607 fail("Stopping the parser did not work as expected");
7608 }
7609 END_TEST
7610
START_TEST(test_misc_stop_during_end_handler_issue_240_2)7611 START_TEST(test_misc_stop_during_end_handler_issue_240_2) {
7612 XML_Parser parser;
7613 DataIssue240 *mydata;
7614 enum XML_Status result;
7615 const char *const doc2 = "<doc><elem/></doc>";
7616
7617 parser = XML_ParserCreate(NULL);
7618 XML_SetElementHandler(parser, start_element_issue_240, end_element_issue_240);
7619 mydata = (DataIssue240 *)malloc(sizeof(DataIssue240));
7620 mydata->parser = parser;
7621 mydata->deep = 0;
7622 XML_SetUserData(parser, mydata);
7623
7624 result = XML_Parse(parser, doc2, (int)strlen(doc2), 1);
7625 XML_ParserFree(parser);
7626 free(mydata);
7627 if (result != XML_STATUS_ERROR)
7628 fail("Stopping the parser did not work as expected");
7629 }
7630 END_TEST
7631
START_TEST(test_misc_deny_internal_entity_closing_doctype_issue_317)7632 START_TEST(test_misc_deny_internal_entity_closing_doctype_issue_317) {
7633 const char *const inputOne = "<!DOCTYPE d [\n"
7634 "<!ENTITY % e ']><d/>'>\n"
7635 "\n"
7636 "%e;";
7637 const char *const inputTwo = "<!DOCTYPE d [\n"
7638 "<!ENTITY % e1 ']><d/>'><!ENTITY % e2 '&e1;'>\n"
7639 "\n"
7640 "%e2;";
7641 const char *const inputThree = "<!DOCTYPE d [\n"
7642 "<!ENTITY % e ']><d'>\n"
7643 "\n"
7644 "%e;";
7645 const char *const inputIssue317 = "<!DOCTYPE doc [\n"
7646 "<!ENTITY % foo ']>\n"
7647 "<doc>Hell<oc (#PCDATA)*>'>\n"
7648 "%foo;\n"
7649 "]>\n"
7650 "<doc>Hello, world</dVc>";
7651
7652 const char *const inputs[] = {inputOne, inputTwo, inputThree, inputIssue317};
7653 size_t inputIndex = 0;
7654
7655 for (; inputIndex < sizeof(inputs) / sizeof(inputs[0]); inputIndex++) {
7656 XML_Parser parser;
7657 enum XML_Status parseResult;
7658 int setParamEntityResult;
7659 XML_Size lineNumber;
7660 XML_Size columnNumber;
7661 const char *const input = inputs[inputIndex];
7662
7663 parser = XML_ParserCreate(NULL);
7664 setParamEntityResult
7665 = XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
7666 if (setParamEntityResult != 1)
7667 fail("Failed to set XML_PARAM_ENTITY_PARSING_ALWAYS.");
7668
7669 parseResult = XML_Parse(parser, input, (int)strlen(input), 0);
7670 if (parseResult != XML_STATUS_ERROR) {
7671 parseResult = XML_Parse(parser, "", 0, 1);
7672 if (parseResult != XML_STATUS_ERROR) {
7673 fail("Parsing was expected to fail but succeeded.");
7674 }
7675 }
7676
7677 if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN)
7678 fail("Error code does not match XML_ERROR_INVALID_TOKEN");
7679
7680 lineNumber = XML_GetCurrentLineNumber(parser);
7681 if (lineNumber != 4)
7682 fail("XML_GetCurrentLineNumber does not work as expected.");
7683
7684 columnNumber = XML_GetCurrentColumnNumber(parser);
7685 if (columnNumber != 0)
7686 fail("XML_GetCurrentColumnNumber does not work as expected.");
7687
7688 XML_ParserFree(parser);
7689 }
7690 }
7691 END_TEST
7692
7693 static int XMLCALL
external_entity_parser_create_alloc_fail_handler(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)7694 external_entity_parser_create_alloc_fail_handler(XML_Parser parser,
7695 const XML_Char *context,
7696 const XML_Char *base,
7697 const XML_Char *systemId,
7698 const XML_Char *publicId) {
7699 UNUSED_P(base);
7700 UNUSED_P(systemId);
7701 UNUSED_P(publicId);
7702
7703 if (context != NULL)
7704 fail("Unexpected non-NULL context");
7705
7706 // The following number intends to fail the upcoming allocation in line
7707 // "parser->m_protocolEncodingName = copyString(encodingName,
7708 // &(parser->m_mem));" in function parserInit.
7709 allocation_count = 3;
7710
7711 const XML_Char *const encodingName = XCS("UTF-8"); // needs something non-NULL
7712 const XML_Parser ext_parser
7713 = XML_ExternalEntityParserCreate(parser, context, encodingName);
7714 if (ext_parser != NULL)
7715 fail(
7716 "Call to XML_ExternalEntityParserCreate was expected to fail out-of-memory");
7717
7718 allocation_count = ALLOC_ALWAYS_SUCCEED;
7719 return XML_STATUS_ERROR;
7720 }
7721
START_TEST(test_alloc_reset_after_external_entity_parser_create_fail)7722 START_TEST(test_alloc_reset_after_external_entity_parser_create_fail) {
7723 const char *const text = "<!DOCTYPE doc SYSTEM 'foo'><doc/>";
7724
7725 XML_SetExternalEntityRefHandler(
7726 g_parser, external_entity_parser_create_alloc_fail_handler);
7727 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
7728
7729 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
7730 != XML_STATUS_ERROR)
7731 fail("Call to parse was expected to fail");
7732
7733 if (XML_GetErrorCode(g_parser) != XML_ERROR_EXTERNAL_ENTITY_HANDLING)
7734 fail("Call to parse was expected to fail from the external entity handler");
7735
7736 XML_ParserReset(g_parser, NULL);
7737 }
7738 END_TEST
7739
7740 static void
alloc_setup(void)7741 alloc_setup(void) {
7742 XML_Memory_Handling_Suite memsuite = {duff_allocator, duff_reallocator, free};
7743
7744 /* Ensure the parser creation will go through */
7745 allocation_count = ALLOC_ALWAYS_SUCCEED;
7746 reallocation_count = REALLOC_ALWAYS_SUCCEED;
7747 g_parser = XML_ParserCreate_MM(NULL, &memsuite, NULL);
7748 if (g_parser == NULL)
7749 fail("Parser not created");
7750 }
7751
7752 static void
alloc_teardown(void)7753 alloc_teardown(void) {
7754 basic_teardown();
7755 }
7756
7757 /* Test the effects of allocation failures on xml declaration processing */
START_TEST(test_alloc_parse_xdecl)7758 START_TEST(test_alloc_parse_xdecl) {
7759 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
7760 "<doc>Hello, world</doc>";
7761 int i;
7762 const int max_alloc_count = 15;
7763
7764 for (i = 0; i < max_alloc_count; i++) {
7765 allocation_count = i;
7766 XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler);
7767 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7768 != XML_STATUS_ERROR)
7769 break;
7770 /* Resetting the parser is insufficient, because some memory
7771 * allocations are cached within the parser. Instead we use
7772 * the teardown and setup routines to ensure that we have the
7773 * right sort of parser back in our hands.
7774 */
7775 alloc_teardown();
7776 alloc_setup();
7777 }
7778 if (i == 0)
7779 fail("Parse succeeded despite failing allocator");
7780 if (i == max_alloc_count)
7781 fail("Parse failed with max allocations");
7782 }
7783 END_TEST
7784
7785 /* As above, but with an encoding big enough to cause storing the
7786 * version information to expand the string pool being used.
7787 */
7788 static int XMLCALL
long_encoding_handler(void * userData,const XML_Char * encoding,XML_Encoding * info)7789 long_encoding_handler(void *userData, const XML_Char *encoding,
7790 XML_Encoding *info) {
7791 int i;
7792
7793 UNUSED_P(userData);
7794 UNUSED_P(encoding);
7795 for (i = 0; i < 256; i++)
7796 info->map[i] = i;
7797 info->data = NULL;
7798 info->convert = NULL;
7799 info->release = NULL;
7800 return XML_STATUS_OK;
7801 }
7802
START_TEST(test_alloc_parse_xdecl_2)7803 START_TEST(test_alloc_parse_xdecl_2) {
7804 const char *text
7805 = "<?xml version='1.0' encoding='"
7806 /* Each line is 64 characters */
7807 "ThisIsAStupidlyLongEncodingNameIntendedToTriggerPoolGrowth123456"
7808 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7809 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7810 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7811 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7812 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7813 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7814 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7815 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7816 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7817 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7818 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7819 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7820 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7821 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7822 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN"
7823 "'?>"
7824 "<doc>Hello, world</doc>";
7825 int i;
7826 const int max_alloc_count = 20;
7827
7828 for (i = 0; i < max_alloc_count; i++) {
7829 allocation_count = i;
7830 XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler);
7831 XML_SetUnknownEncodingHandler(g_parser, long_encoding_handler, NULL);
7832 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7833 != XML_STATUS_ERROR)
7834 break;
7835 /* See comment in test_alloc_parse_xdecl() */
7836 alloc_teardown();
7837 alloc_setup();
7838 }
7839 if (i == 0)
7840 fail("Parse succeeded despite failing allocator");
7841 if (i == max_alloc_count)
7842 fail("Parse failed with max allocations");
7843 }
7844 END_TEST
7845
7846 /* Test the effects of allocation failures on a straightforward parse */
START_TEST(test_alloc_parse_pi)7847 START_TEST(test_alloc_parse_pi) {
7848 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
7849 "<?pi unknown?>\n"
7850 "<doc>"
7851 "Hello, world"
7852 "</doc>";
7853 int i;
7854 const int max_alloc_count = 15;
7855
7856 for (i = 0; i < max_alloc_count; i++) {
7857 allocation_count = i;
7858 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
7859 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7860 != XML_STATUS_ERROR)
7861 break;
7862 /* See comment in test_alloc_parse_xdecl() */
7863 alloc_teardown();
7864 alloc_setup();
7865 }
7866 if (i == 0)
7867 fail("Parse succeeded despite failing allocator");
7868 if (i == max_alloc_count)
7869 fail("Parse failed with max allocations");
7870 }
7871 END_TEST
7872
START_TEST(test_alloc_parse_pi_2)7873 START_TEST(test_alloc_parse_pi_2) {
7874 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
7875 "<doc>"
7876 "Hello, world"
7877 "<?pi unknown?>\n"
7878 "</doc>";
7879 int i;
7880 const int max_alloc_count = 15;
7881
7882 for (i = 0; i < max_alloc_count; i++) {
7883 allocation_count = i;
7884 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
7885 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7886 != XML_STATUS_ERROR)
7887 break;
7888 /* See comment in test_alloc_parse_xdecl() */
7889 alloc_teardown();
7890 alloc_setup();
7891 }
7892 if (i == 0)
7893 fail("Parse succeeded despite failing allocator");
7894 if (i == max_alloc_count)
7895 fail("Parse failed with max allocations");
7896 }
7897 END_TEST
7898
START_TEST(test_alloc_parse_pi_3)7899 START_TEST(test_alloc_parse_pi_3) {
7900 const char *text
7901 = "<?"
7902 /* 64 characters per line */
7903 "This processing instruction should be long enough to ensure that"
7904 "it triggers the growth of an internal string pool when the "
7905 "allocator fails at a cruicial moment FGHIJKLMNOPABCDEFGHIJKLMNOP"
7906 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7907 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7908 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7909 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7910 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7911 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7912 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7913 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7914 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7915 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7916 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7917 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7918 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7919 "Q?><doc/>";
7920 int i;
7921 const int max_alloc_count = 20;
7922
7923 for (i = 0; i < max_alloc_count; i++) {
7924 allocation_count = i;
7925 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
7926 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7927 != XML_STATUS_ERROR)
7928 break;
7929 /* See comment in test_alloc_parse_xdecl() */
7930 alloc_teardown();
7931 alloc_setup();
7932 }
7933 if (i == 0)
7934 fail("Parse succeeded despite failing allocator");
7935 if (i == max_alloc_count)
7936 fail("Parse failed with max allocations");
7937 }
7938 END_TEST
7939
START_TEST(test_alloc_parse_comment)7940 START_TEST(test_alloc_parse_comment) {
7941 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
7942 "<!-- Test parsing this comment -->"
7943 "<doc>Hi</doc>";
7944 int i;
7945 const int max_alloc_count = 15;
7946
7947 for (i = 0; i < max_alloc_count; i++) {
7948 allocation_count = i;
7949 XML_SetCommentHandler(g_parser, dummy_comment_handler);
7950 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7951 != XML_STATUS_ERROR)
7952 break;
7953 /* See comment in test_alloc_parse_xdecl() */
7954 alloc_teardown();
7955 alloc_setup();
7956 }
7957 if (i == 0)
7958 fail("Parse succeeded despite failing allocator");
7959 if (i == max_alloc_count)
7960 fail("Parse failed with max allocations");
7961 }
7962 END_TEST
7963
START_TEST(test_alloc_parse_comment_2)7964 START_TEST(test_alloc_parse_comment_2) {
7965 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
7966 "<doc>"
7967 "Hello, world"
7968 "<!-- Parse this comment too -->"
7969 "</doc>";
7970 int i;
7971 const int max_alloc_count = 15;
7972
7973 for (i = 0; i < max_alloc_count; i++) {
7974 allocation_count = i;
7975 XML_SetCommentHandler(g_parser, dummy_comment_handler);
7976 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7977 != XML_STATUS_ERROR)
7978 break;
7979 /* See comment in test_alloc_parse_xdecl() */
7980 alloc_teardown();
7981 alloc_setup();
7982 }
7983 if (i == 0)
7984 fail("Parse succeeded despite failing allocator");
7985 if (i == max_alloc_count)
7986 fail("Parse failed with max allocations");
7987 }
7988 END_TEST
7989
7990 static int XMLCALL
external_entity_duff_loader(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)7991 external_entity_duff_loader(XML_Parser parser, const XML_Char *context,
7992 const XML_Char *base, const XML_Char *systemId,
7993 const XML_Char *publicId) {
7994 XML_Parser new_parser;
7995 unsigned int i;
7996 const unsigned int max_alloc_count = 10;
7997
7998 UNUSED_P(base);
7999 UNUSED_P(systemId);
8000 UNUSED_P(publicId);
8001 /* Try a few different allocation levels */
8002 for (i = 0; i < max_alloc_count; i++) {
8003 allocation_count = i;
8004 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8005 if (new_parser != NULL) {
8006 XML_ParserFree(new_parser);
8007 break;
8008 }
8009 }
8010 if (i == 0)
8011 fail("External parser creation ignored failing allocator");
8012 else if (i == max_alloc_count)
8013 fail("Extern parser not created with max allocation count");
8014
8015 /* Make sure other random allocation doesn't now fail */
8016 allocation_count = ALLOC_ALWAYS_SUCCEED;
8017
8018 /* Make sure the failure code path is executed too */
8019 return XML_STATUS_ERROR;
8020 }
8021
8022 /* Test that external parser creation running out of memory is
8023 * correctly reported. Based on the external entity test cases.
8024 */
START_TEST(test_alloc_create_external_parser)8025 START_TEST(test_alloc_create_external_parser) {
8026 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
8027 "<!DOCTYPE doc SYSTEM 'foo'>\n"
8028 "<doc>&entity;</doc>";
8029 char foo_text[] = "<!ELEMENT doc (#PCDATA)*>";
8030
8031 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8032 XML_SetUserData(g_parser, foo_text);
8033 XML_SetExternalEntityRefHandler(g_parser, external_entity_duff_loader);
8034 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8035 != XML_STATUS_ERROR) {
8036 fail("External parser allocator returned success incorrectly");
8037 }
8038 }
8039 END_TEST
8040
8041 /* More external parser memory allocation testing */
START_TEST(test_alloc_run_external_parser)8042 START_TEST(test_alloc_run_external_parser) {
8043 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
8044 "<!DOCTYPE doc SYSTEM 'foo'>\n"
8045 "<doc>&entity;</doc>";
8046 char foo_text[] = "<!ELEMENT doc (#PCDATA)*>";
8047 unsigned int i;
8048 const unsigned int max_alloc_count = 15;
8049
8050 for (i = 0; i < max_alloc_count; i++) {
8051 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8052 XML_SetUserData(g_parser, foo_text);
8053 XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader);
8054 allocation_count = i;
8055 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8056 != XML_STATUS_ERROR)
8057 break;
8058 /* See comment in test_alloc_parse_xdecl() */
8059 alloc_teardown();
8060 alloc_setup();
8061 }
8062 if (i == 0)
8063 fail("Parsing ignored failing allocator");
8064 else if (i == max_alloc_count)
8065 fail("Parsing failed with allocation count 10");
8066 }
8067 END_TEST
8068
8069 static int XMLCALL
external_entity_dbl_handler(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)8070 external_entity_dbl_handler(XML_Parser parser, const XML_Char *context,
8071 const XML_Char *base, const XML_Char *systemId,
8072 const XML_Char *publicId) {
8073 intptr_t callno = (intptr_t)XML_GetUserData(parser);
8074 const char *text;
8075 XML_Parser new_parser;
8076 int i;
8077 const int max_alloc_count = 20;
8078
8079 UNUSED_P(base);
8080 UNUSED_P(systemId);
8081 UNUSED_P(publicId);
8082 if (callno == 0) {
8083 /* First time through, check how many calls to malloc occur */
8084 text = ("<!ELEMENT doc (e+)>\n"
8085 "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
8086 "<!ELEMENT e EMPTY>\n");
8087 allocation_count = 10000;
8088 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8089 if (new_parser == NULL) {
8090 fail("Unable to allocate first external parser");
8091 return XML_STATUS_ERROR;
8092 }
8093 /* Stash the number of calls in the user data */
8094 XML_SetUserData(parser, (void *)(intptr_t)(10000 - allocation_count));
8095 } else {
8096 text = ("<?xml version='1.0' encoding='us-ascii'?>"
8097 "<e/>");
8098 /* Try at varying levels to exercise more code paths */
8099 for (i = 0; i < max_alloc_count; i++) {
8100 allocation_count = callno + i;
8101 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8102 if (new_parser != NULL)
8103 break;
8104 }
8105 if (i == 0) {
8106 fail("Second external parser unexpectedly created");
8107 XML_ParserFree(new_parser);
8108 return XML_STATUS_ERROR;
8109 } else if (i == max_alloc_count) {
8110 fail("Second external parser not created");
8111 return XML_STATUS_ERROR;
8112 }
8113 }
8114
8115 allocation_count = ALLOC_ALWAYS_SUCCEED;
8116 if (_XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE)
8117 == XML_STATUS_ERROR) {
8118 xml_failure(new_parser);
8119 return XML_STATUS_ERROR;
8120 }
8121 XML_ParserFree(new_parser);
8122 return XML_STATUS_OK;
8123 }
8124
8125 /* Test that running out of memory in dtdCopy is correctly reported.
8126 * Based on test_default_ns_from_ext_subset_and_ext_ge()
8127 */
START_TEST(test_alloc_dtd_copy_default_atts)8128 START_TEST(test_alloc_dtd_copy_default_atts) {
8129 const char *text = "<?xml version='1.0'?>\n"
8130 "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n"
8131 " <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n"
8132 "]>\n"
8133 "<doc xmlns='http://example.org/ns1'>\n"
8134 "&en;\n"
8135 "</doc>";
8136
8137 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8138 XML_SetExternalEntityRefHandler(g_parser, external_entity_dbl_handler);
8139 XML_SetUserData(g_parser, NULL);
8140 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8141 == XML_STATUS_ERROR)
8142 xml_failure(g_parser);
8143 }
8144 END_TEST
8145
8146 static int XMLCALL
external_entity_dbl_handler_2(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)8147 external_entity_dbl_handler_2(XML_Parser parser, const XML_Char *context,
8148 const XML_Char *base, const XML_Char *systemId,
8149 const XML_Char *publicId) {
8150 intptr_t callno = (intptr_t)XML_GetUserData(parser);
8151 const char *text;
8152 XML_Parser new_parser;
8153 enum XML_Status rv;
8154
8155 UNUSED_P(base);
8156 UNUSED_P(systemId);
8157 UNUSED_P(publicId);
8158 if (callno == 0) {
8159 /* Try different allocation levels for whole exercise */
8160 text = ("<!ELEMENT doc (e+)>\n"
8161 "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
8162 "<!ELEMENT e EMPTY>\n");
8163 XML_SetUserData(parser, (void *)(intptr_t)1);
8164 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8165 if (new_parser == NULL)
8166 return XML_STATUS_ERROR;
8167 rv = _XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE);
8168 } else {
8169 /* Just run through once */
8170 text = ("<?xml version='1.0' encoding='us-ascii'?>"
8171 "<e/>");
8172 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8173 if (new_parser == NULL)
8174 return XML_STATUS_ERROR;
8175 rv = _XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE);
8176 }
8177 XML_ParserFree(new_parser);
8178 if (rv == XML_STATUS_ERROR)
8179 return XML_STATUS_ERROR;
8180 return XML_STATUS_OK;
8181 }
8182
8183 /* Test more external entity allocation failure paths */
START_TEST(test_alloc_external_entity)8184 START_TEST(test_alloc_external_entity) {
8185 const char *text = "<?xml version='1.0'?>\n"
8186 "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n"
8187 " <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n"
8188 "]>\n"
8189 "<doc xmlns='http://example.org/ns1'>\n"
8190 "&en;\n"
8191 "</doc>";
8192 int i;
8193 const int alloc_test_max_repeats = 50;
8194
8195 for (i = 0; i < alloc_test_max_repeats; i++) {
8196 allocation_count = -1;
8197 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8198 XML_SetExternalEntityRefHandler(g_parser, external_entity_dbl_handler_2);
8199 XML_SetUserData(g_parser, NULL);
8200 allocation_count = i;
8201 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8202 == XML_STATUS_OK)
8203 break;
8204 /* See comment in test_alloc_parse_xdecl() */
8205 alloc_teardown();
8206 alloc_setup();
8207 }
8208 allocation_count = -1;
8209 if (i == 0)
8210 fail("External entity parsed despite duff allocator");
8211 if (i == alloc_test_max_repeats)
8212 fail("External entity not parsed at max allocation count");
8213 }
8214 END_TEST
8215
8216 /* Test more allocation failure paths */
8217 static int XMLCALL
external_entity_alloc_set_encoding(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)8218 external_entity_alloc_set_encoding(XML_Parser parser, const XML_Char *context,
8219 const XML_Char *base,
8220 const XML_Char *systemId,
8221 const XML_Char *publicId) {
8222 /* As for external_entity_loader() */
8223 const char *text = "<?xml encoding='iso-8859-3'?>"
8224 "\xC3\xA9";
8225 XML_Parser ext_parser;
8226 enum XML_Status status;
8227
8228 UNUSED_P(base);
8229 UNUSED_P(systemId);
8230 UNUSED_P(publicId);
8231 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8232 if (ext_parser == NULL)
8233 return XML_STATUS_ERROR;
8234 if (! XML_SetEncoding(ext_parser, XCS("utf-8"))) {
8235 XML_ParserFree(ext_parser);
8236 return XML_STATUS_ERROR;
8237 }
8238 status
8239 = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
8240 XML_ParserFree(ext_parser);
8241 if (status == XML_STATUS_ERROR)
8242 return XML_STATUS_ERROR;
8243 return XML_STATUS_OK;
8244 }
8245
START_TEST(test_alloc_ext_entity_set_encoding)8246 START_TEST(test_alloc_ext_entity_set_encoding) {
8247 const char *text = "<!DOCTYPE doc [\n"
8248 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
8249 "]>\n"
8250 "<doc>&en;</doc>";
8251 int i;
8252 const int max_allocation_count = 30;
8253
8254 for (i = 0; i < max_allocation_count; i++) {
8255 XML_SetExternalEntityRefHandler(g_parser,
8256 external_entity_alloc_set_encoding);
8257 allocation_count = i;
8258 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8259 == XML_STATUS_OK)
8260 break;
8261 allocation_count = -1;
8262 /* See comment in test_alloc_parse_xdecl() */
8263 alloc_teardown();
8264 alloc_setup();
8265 }
8266 if (i == 0)
8267 fail("Encoding check succeeded despite failing allocator");
8268 if (i == max_allocation_count)
8269 fail("Encoding failed at max allocation count");
8270 }
8271 END_TEST
8272
8273 static int XMLCALL
unknown_released_encoding_handler(void * data,const XML_Char * encoding,XML_Encoding * info)8274 unknown_released_encoding_handler(void *data, const XML_Char *encoding,
8275 XML_Encoding *info) {
8276 UNUSED_P(data);
8277 if (! xcstrcmp(encoding, XCS("unsupported-encoding"))) {
8278 int i;
8279
8280 for (i = 0; i < 256; i++)
8281 info->map[i] = i;
8282 info->data = NULL;
8283 info->convert = NULL;
8284 info->release = dummy_release;
8285 return XML_STATUS_OK;
8286 }
8287 return XML_STATUS_ERROR;
8288 }
8289
8290 /* Test the effects of allocation failure in internal entities.
8291 * Based on test_unknown_encoding_internal_entity
8292 */
START_TEST(test_alloc_internal_entity)8293 START_TEST(test_alloc_internal_entity) {
8294 const char *text = "<?xml version='1.0' encoding='unsupported-encoding'?>\n"
8295 "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n"
8296 "<test a='&foo;'/>";
8297 unsigned int i;
8298 const unsigned int max_alloc_count = 20;
8299
8300 for (i = 0; i < max_alloc_count; i++) {
8301 allocation_count = i;
8302 XML_SetUnknownEncodingHandler(g_parser, unknown_released_encoding_handler,
8303 NULL);
8304 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8305 != XML_STATUS_ERROR)
8306 break;
8307 /* See comment in test_alloc_parse_xdecl() */
8308 alloc_teardown();
8309 alloc_setup();
8310 }
8311 if (i == 0)
8312 fail("Internal entity worked despite failing allocations");
8313 else if (i == max_alloc_count)
8314 fail("Internal entity failed at max allocation count");
8315 }
8316 END_TEST
8317
8318 /* Test the robustness against allocation failure of element handling
8319 * Based on test_dtd_default_handling().
8320 */
START_TEST(test_alloc_dtd_default_handling)8321 START_TEST(test_alloc_dtd_default_handling) {
8322 const char *text = "<!DOCTYPE doc [\n"
8323 "<!ENTITY e SYSTEM 'http://example.org/e'>\n"
8324 "<!NOTATION n SYSTEM 'http://example.org/n'>\n"
8325 "<!ENTITY e1 SYSTEM 'http://example.org/e' NDATA n>\n"
8326 "<!ELEMENT doc (#PCDATA)>\n"
8327 "<!ATTLIST doc a CDATA #IMPLIED>\n"
8328 "<?pi in dtd?>\n"
8329 "<!--comment in dtd-->\n"
8330 "]>\n"
8331 "<doc><![CDATA[text in doc]]></doc>";
8332 const XML_Char *expected = XCS("\n\n\n\n\n\n\n\n\n<doc>text in doc</doc>");
8333 CharData storage;
8334 int i;
8335 const int max_alloc_count = 25;
8336
8337 for (i = 0; i < max_alloc_count; i++) {
8338 allocation_count = i;
8339 dummy_handler_flags = 0;
8340 XML_SetDefaultHandler(g_parser, accumulate_characters);
8341 XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_handler,
8342 dummy_end_doctype_handler);
8343 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
8344 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
8345 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
8346 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
8347 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
8348 XML_SetCommentHandler(g_parser, dummy_comment_handler);
8349 XML_SetCdataSectionHandler(g_parser, dummy_start_cdata_handler,
8350 dummy_end_cdata_handler);
8351 XML_SetUnparsedEntityDeclHandler(g_parser,
8352 dummy_unparsed_entity_decl_handler);
8353 CharData_Init(&storage);
8354 XML_SetUserData(g_parser, &storage);
8355 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
8356 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8357 != XML_STATUS_ERROR)
8358 break;
8359 /* See comment in test_alloc_parse_xdecl() */
8360 alloc_teardown();
8361 alloc_setup();
8362 }
8363 if (i == 0)
8364 fail("Default DTD parsed despite allocation failures");
8365 if (i == max_alloc_count)
8366 fail("Default DTD not parsed with maximum alloc count");
8367 CharData_CheckXMLChars(&storage, expected);
8368 if (dummy_handler_flags
8369 != (DUMMY_START_DOCTYPE_HANDLER_FLAG | DUMMY_END_DOCTYPE_HANDLER_FLAG
8370 | DUMMY_ENTITY_DECL_HANDLER_FLAG | DUMMY_NOTATION_DECL_HANDLER_FLAG
8371 | DUMMY_ELEMENT_DECL_HANDLER_FLAG | DUMMY_ATTLIST_DECL_HANDLER_FLAG
8372 | DUMMY_COMMENT_HANDLER_FLAG | DUMMY_PI_HANDLER_FLAG
8373 | DUMMY_START_CDATA_HANDLER_FLAG | DUMMY_END_CDATA_HANDLER_FLAG
8374 | DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG))
8375 fail("Not all handlers were called");
8376 }
8377 END_TEST
8378
8379 /* Test robustness of XML_SetEncoding() with a failing allocator */
START_TEST(test_alloc_explicit_encoding)8380 START_TEST(test_alloc_explicit_encoding) {
8381 int i;
8382 const int max_alloc_count = 5;
8383
8384 for (i = 0; i < max_alloc_count; i++) {
8385 allocation_count = i;
8386 if (XML_SetEncoding(g_parser, XCS("us-ascii")) == XML_STATUS_OK)
8387 break;
8388 }
8389 if (i == 0)
8390 fail("Encoding set despite failing allocator");
8391 else if (i == max_alloc_count)
8392 fail("Encoding not set at max allocation count");
8393 }
8394 END_TEST
8395
8396 /* Test robustness of XML_SetBase against a failing allocator */
START_TEST(test_alloc_set_base)8397 START_TEST(test_alloc_set_base) {
8398 const XML_Char *new_base = XCS("/local/file/name.xml");
8399 int i;
8400 const int max_alloc_count = 5;
8401
8402 for (i = 0; i < max_alloc_count; i++) {
8403 allocation_count = i;
8404 if (XML_SetBase(g_parser, new_base) == XML_STATUS_OK)
8405 break;
8406 }
8407 if (i == 0)
8408 fail("Base set despite failing allocator");
8409 else if (i == max_alloc_count)
8410 fail("Base not set with max allocation count");
8411 }
8412 END_TEST
8413
8414 /* Test buffer extension in the face of a duff reallocator */
START_TEST(test_alloc_realloc_buffer)8415 START_TEST(test_alloc_realloc_buffer) {
8416 const char *text = get_buffer_test_text;
8417 void *buffer;
8418 int i;
8419 const int max_realloc_count = 10;
8420
8421 /* Get a smallish buffer */
8422 for (i = 0; i < max_realloc_count; i++) {
8423 reallocation_count = i;
8424 buffer = XML_GetBuffer(g_parser, 1536);
8425 if (buffer == NULL)
8426 fail("1.5K buffer reallocation failed");
8427 assert(buffer != NULL);
8428 memcpy(buffer, text, strlen(text));
8429 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE)
8430 == XML_STATUS_OK)
8431 break;
8432 /* See comment in test_alloc_parse_xdecl() */
8433 alloc_teardown();
8434 alloc_setup();
8435 }
8436 reallocation_count = -1;
8437 if (i == 0)
8438 fail("Parse succeeded with no reallocation");
8439 else if (i == max_realloc_count)
8440 fail("Parse failed with max reallocation count");
8441 }
8442 END_TEST
8443
8444 /* Same test for external entity parsers */
8445 static int XMLCALL
external_entity_reallocator(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)8446 external_entity_reallocator(XML_Parser parser, const XML_Char *context,
8447 const XML_Char *base, const XML_Char *systemId,
8448 const XML_Char *publicId) {
8449 const char *text = get_buffer_test_text;
8450 XML_Parser ext_parser;
8451 void *buffer;
8452 enum XML_Status status;
8453
8454 UNUSED_P(base);
8455 UNUSED_P(systemId);
8456 UNUSED_P(publicId);
8457 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8458 if (ext_parser == NULL)
8459 fail("Could not create external entity parser");
8460
8461 reallocation_count = (intptr_t)XML_GetUserData(parser);
8462 buffer = XML_GetBuffer(ext_parser, 1536);
8463 if (buffer == NULL)
8464 fail("Buffer allocation failed");
8465 assert(buffer != NULL);
8466 memcpy(buffer, text, strlen(text));
8467 status = XML_ParseBuffer(ext_parser, (int)strlen(text), XML_FALSE);
8468 reallocation_count = -1;
8469 XML_ParserFree(ext_parser);
8470 return (status == XML_STATUS_OK) ? XML_STATUS_OK : XML_STATUS_ERROR;
8471 }
8472
START_TEST(test_alloc_ext_entity_realloc_buffer)8473 START_TEST(test_alloc_ext_entity_realloc_buffer) {
8474 const char *text = "<!DOCTYPE doc [\n"
8475 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
8476 "]>\n"
8477 "<doc>&en;</doc>";
8478 int i;
8479 const int max_realloc_count = 10;
8480
8481 for (i = 0; i < max_realloc_count; i++) {
8482 XML_SetExternalEntityRefHandler(g_parser, external_entity_reallocator);
8483 XML_SetUserData(g_parser, (void *)(intptr_t)i);
8484 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8485 == XML_STATUS_OK)
8486 break;
8487 /* See comment in test_alloc_parse_xdecl() */
8488 alloc_teardown();
8489 alloc_setup();
8490 }
8491 if (i == 0)
8492 fail("Succeeded with no reallocations");
8493 if (i == max_realloc_count)
8494 fail("Failed with max reallocations");
8495 }
8496 END_TEST
8497
8498 /* Test elements with many attributes are handled correctly */
START_TEST(test_alloc_realloc_many_attributes)8499 START_TEST(test_alloc_realloc_many_attributes) {
8500 const char *text = "<!DOCTYPE doc [\n"
8501 "<!ATTLIST doc za CDATA 'default'>\n"
8502 "<!ATTLIST doc zb CDATA 'def2'>\n"
8503 "<!ATTLIST doc zc CDATA 'def3'>\n"
8504 "]>\n"
8505 "<doc a='1'"
8506 " b='2'"
8507 " c='3'"
8508 " d='4'"
8509 " e='5'"
8510 " f='6'"
8511 " g='7'"
8512 " h='8'"
8513 " i='9'"
8514 " j='10'"
8515 " k='11'"
8516 " l='12'"
8517 " m='13'"
8518 " n='14'"
8519 " p='15'"
8520 " q='16'"
8521 " r='17'"
8522 " s='18'>"
8523 "</doc>";
8524 int i;
8525 const int max_realloc_count = 10;
8526
8527 for (i = 0; i < max_realloc_count; i++) {
8528 reallocation_count = i;
8529 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8530 != XML_STATUS_ERROR)
8531 break;
8532 /* See comment in test_alloc_parse_xdecl() */
8533 alloc_teardown();
8534 alloc_setup();
8535 }
8536 if (i == 0)
8537 fail("Parse succeeded despite no reallocations");
8538 if (i == max_realloc_count)
8539 fail("Parse failed at max reallocations");
8540 }
8541 END_TEST
8542
8543 /* Test handling of a public entity with failing allocator */
START_TEST(test_alloc_public_entity_value)8544 START_TEST(test_alloc_public_entity_value) {
8545 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
8546 "<doc></doc>\n";
8547 char dtd_text[]
8548 = "<!ELEMENT doc EMPTY>\n"
8549 "<!ENTITY % e1 PUBLIC 'foo' 'bar.ent'>\n"
8550 "<!ENTITY % "
8551 /* Each line is 64 characters */
8552 "ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345"
8553 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8554 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8555 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8556 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8557 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8558 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8559 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8560 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8561 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8562 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8563 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8564 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8565 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8566 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8567 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8568 " '%e1;'>\n"
8569 "%e1;\n";
8570 int i;
8571 const int max_alloc_count = 50;
8572
8573 for (i = 0; i < max_alloc_count; i++) {
8574 allocation_count = i;
8575 dummy_handler_flags = 0;
8576 XML_SetUserData(g_parser, dtd_text);
8577 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8578 XML_SetExternalEntityRefHandler(g_parser, external_entity_public);
8579 /* Provoke a particular code path */
8580 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
8581 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8582 != XML_STATUS_ERROR)
8583 break;
8584 /* See comment in test_alloc_parse_xdecl() */
8585 alloc_teardown();
8586 alloc_setup();
8587 }
8588 if (i == 0)
8589 fail("Parsing worked despite failing allocation");
8590 if (i == max_alloc_count)
8591 fail("Parsing failed at max allocation count");
8592 if (dummy_handler_flags != DUMMY_ENTITY_DECL_HANDLER_FLAG)
8593 fail("Entity declaration handler not called");
8594 }
8595 END_TEST
8596
START_TEST(test_alloc_realloc_subst_public_entity_value)8597 START_TEST(test_alloc_realloc_subst_public_entity_value) {
8598 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
8599 "<doc></doc>\n";
8600 char dtd_text[]
8601 = "<!ELEMENT doc EMPTY>\n"
8602 "<!ENTITY % "
8603 /* Each line is 64 characters */
8604 "ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345"
8605 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8606 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8607 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8608 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8609 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8610 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8611 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8612 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8613 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8614 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8615 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8616 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8617 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8618 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8619 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8620 " PUBLIC 'foo' 'bar.ent'>\n"
8621 "%ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345"
8622 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8623 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8624 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8625 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8626 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8627 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8628 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8629 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8630 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8631 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8632 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8633 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8634 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8635 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8636 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP;";
8637 int i;
8638 const int max_realloc_count = 10;
8639
8640 for (i = 0; i < max_realloc_count; i++) {
8641 reallocation_count = i;
8642 XML_SetUserData(g_parser, dtd_text);
8643 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8644 XML_SetExternalEntityRefHandler(g_parser, external_entity_public);
8645 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8646 != XML_STATUS_ERROR)
8647 break;
8648 /* See comment in test_alloc_parse_xdecl() */
8649 alloc_teardown();
8650 alloc_setup();
8651 }
8652 if (i == 0)
8653 fail("Parsing worked despite failing reallocation");
8654 if (i == max_realloc_count)
8655 fail("Parsing failed at max reallocation count");
8656 }
8657 END_TEST
8658
START_TEST(test_alloc_parse_public_doctype)8659 START_TEST(test_alloc_parse_public_doctype) {
8660 const char *text
8661 = "<?xml version='1.0' encoding='utf-8'?>\n"
8662 "<!DOCTYPE doc PUBLIC '"
8663 /* 64 characters per line */
8664 "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/"
8665 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8666 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8667 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8668 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8669 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8670 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8671 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8672 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8673 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8674 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8675 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8676 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8677 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8678 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8679 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8680 "' 'test'>\n"
8681 "<doc></doc>";
8682 int i;
8683 const int max_alloc_count = 25;
8684
8685 for (i = 0; i < max_alloc_count; i++) {
8686 allocation_count = i;
8687 dummy_handler_flags = 0;
8688 XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_decl_handler,
8689 dummy_end_doctype_decl_handler);
8690 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8691 != XML_STATUS_ERROR)
8692 break;
8693 /* See comment in test_alloc_parse_xdecl() */
8694 alloc_teardown();
8695 alloc_setup();
8696 }
8697 if (i == 0)
8698 fail("Parse succeeded despite failing allocator");
8699 if (i == max_alloc_count)
8700 fail("Parse failed at maximum allocation count");
8701 if (dummy_handler_flags
8702 != (DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG
8703 | DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG))
8704 fail("Doctype handler functions not called");
8705 }
8706 END_TEST
8707
START_TEST(test_alloc_parse_public_doctype_long_name)8708 START_TEST(test_alloc_parse_public_doctype_long_name) {
8709 const char *text
8710 = "<?xml version='1.0' encoding='utf-8'?>\n"
8711 "<!DOCTYPE doc PUBLIC 'http://example.com/foo' '"
8712 /* 64 characters per line */
8713 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8714 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8715 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8716 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8717 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8718 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8719 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8720 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8721 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8722 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8723 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8724 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8725 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8726 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8727 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8728 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8729 "'>\n"
8730 "<doc></doc>";
8731 int i;
8732 const int max_alloc_count = 25;
8733
8734 for (i = 0; i < max_alloc_count; i++) {
8735 allocation_count = i;
8736 XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_decl_handler,
8737 dummy_end_doctype_decl_handler);
8738 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8739 != XML_STATUS_ERROR)
8740 break;
8741 /* See comment in test_alloc_parse_xdecl() */
8742 alloc_teardown();
8743 alloc_setup();
8744 }
8745 if (i == 0)
8746 fail("Parse succeeded despite failing allocator");
8747 if (i == max_alloc_count)
8748 fail("Parse failed at maximum allocation count");
8749 }
8750 END_TEST
8751
8752 static int XMLCALL
external_entity_alloc(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)8753 external_entity_alloc(XML_Parser parser, const XML_Char *context,
8754 const XML_Char *base, const XML_Char *systemId,
8755 const XML_Char *publicId) {
8756 const char *text = (const char *)XML_GetUserData(parser);
8757 XML_Parser ext_parser;
8758 int parse_res;
8759
8760 UNUSED_P(base);
8761 UNUSED_P(systemId);
8762 UNUSED_P(publicId);
8763 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8764 if (ext_parser == NULL)
8765 return XML_STATUS_ERROR;
8766 parse_res
8767 = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
8768 XML_ParserFree(ext_parser);
8769 return parse_res;
8770 }
8771
8772 /* Test foreign DTD handling */
START_TEST(test_alloc_set_foreign_dtd)8773 START_TEST(test_alloc_set_foreign_dtd) {
8774 const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n"
8775 "<doc>&entity;</doc>";
8776 char text2[] = "<!ELEMENT doc (#PCDATA)*>";
8777 int i;
8778 const int max_alloc_count = 25;
8779
8780 for (i = 0; i < max_alloc_count; i++) {
8781 allocation_count = i;
8782 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8783 XML_SetUserData(g_parser, &text2);
8784 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
8785 if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE)
8786 fail("Could not set foreign DTD");
8787 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_TRUE)
8788 != XML_STATUS_ERROR)
8789 break;
8790 /* See comment in test_alloc_parse_xdecl() */
8791 alloc_teardown();
8792 alloc_setup();
8793 }
8794 if (i == 0)
8795 fail("Parse succeeded despite failing allocator");
8796 if (i == max_alloc_count)
8797 fail("Parse failed at maximum allocation count");
8798 }
8799 END_TEST
8800
8801 /* Test based on ibm/valid/P32/ibm32v04.xml */
START_TEST(test_alloc_attribute_enum_value)8802 START_TEST(test_alloc_attribute_enum_value) {
8803 const char *text = "<?xml version='1.0' standalone='no'?>\n"
8804 "<!DOCTYPE animal SYSTEM 'test.dtd'>\n"
8805 "<animal>This is a \n <a/> \n\nyellow tiger</animal>";
8806 char dtd_text[] = "<!ELEMENT animal (#PCDATA|a)*>\n"
8807 "<!ELEMENT a EMPTY>\n"
8808 "<!ATTLIST animal xml:space (default|preserve) 'preserve'>";
8809 int i;
8810 const int max_alloc_count = 30;
8811
8812 for (i = 0; i < max_alloc_count; i++) {
8813 allocation_count = i;
8814 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
8815 XML_SetUserData(g_parser, dtd_text);
8816 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8817 /* An attribute list handler provokes a different code path */
8818 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
8819 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8820 != XML_STATUS_ERROR)
8821 break;
8822 /* See comment in test_alloc_parse_xdecl() */
8823 alloc_teardown();
8824 alloc_setup();
8825 }
8826 if (i == 0)
8827 fail("Parse succeeded despite failing allocator");
8828 if (i == max_alloc_count)
8829 fail("Parse failed at maximum allocation count");
8830 }
8831 END_TEST
8832
8833 /* Test attribute enums sufficient to overflow the string pool */
START_TEST(test_alloc_realloc_attribute_enum_value)8834 START_TEST(test_alloc_realloc_attribute_enum_value) {
8835 const char *text = "<?xml version='1.0' standalone='no'?>\n"
8836 "<!DOCTYPE animal SYSTEM 'test.dtd'>\n"
8837 "<animal>This is a yellow tiger</animal>";
8838 /* We wish to define a collection of attribute enums that will
8839 * cause the string pool storing them to have to expand. This
8840 * means more than 1024 bytes, including the parentheses and
8841 * separator bars.
8842 */
8843 char dtd_text[]
8844 = "<!ELEMENT animal (#PCDATA)*>\n"
8845 "<!ATTLIST animal thing "
8846 "(default"
8847 /* Each line is 64 characters */
8848 "|ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8849 "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8850 "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8851 "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8852 "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8853 "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8854 "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8855 "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8856 "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8857 "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8858 "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8859 "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8860 "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8861 "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8862 "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8863 "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO)"
8864 " 'default'>";
8865 int i;
8866 const int max_realloc_count = 10;
8867
8868 for (i = 0; i < max_realloc_count; i++) {
8869 reallocation_count = i;
8870 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
8871 XML_SetUserData(g_parser, dtd_text);
8872 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8873 /* An attribute list handler provokes a different code path */
8874 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
8875 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8876 != XML_STATUS_ERROR)
8877 break;
8878 /* See comment in test_alloc_parse_xdecl() */
8879 alloc_teardown();
8880 alloc_setup();
8881 }
8882 if (i == 0)
8883 fail("Parse succeeded despite failing reallocator");
8884 if (i == max_realloc_count)
8885 fail("Parse failed at maximum reallocation count");
8886 }
8887 END_TEST
8888
8889 /* Test attribute enums in a #IMPLIED attribute forcing pool growth */
START_TEST(test_alloc_realloc_implied_attribute)8890 START_TEST(test_alloc_realloc_implied_attribute) {
8891 /* Forcing this particular code path is a balancing act. The
8892 * addition of the closing parenthesis and terminal NUL must be
8893 * what pushes the string of enums over the 1024-byte limit,
8894 * otherwise a different code path will pick up the realloc.
8895 */
8896 const char *text
8897 = "<!DOCTYPE doc [\n"
8898 "<!ELEMENT doc EMPTY>\n"
8899 "<!ATTLIST doc a "
8900 /* Each line is 64 characters */
8901 "(ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8902 "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8903 "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8904 "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8905 "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8906 "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8907 "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8908 "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8909 "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8910 "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8911 "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8912 "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8913 "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8914 "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8915 "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8916 "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN)"
8917 " #IMPLIED>\n"
8918 "]><doc/>";
8919 int i;
8920 const int max_realloc_count = 10;
8921
8922 for (i = 0; i < max_realloc_count; i++) {
8923 reallocation_count = i;
8924 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
8925 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8926 != XML_STATUS_ERROR)
8927 break;
8928 /* See comment in test_alloc_parse_xdecl() */
8929 alloc_teardown();
8930 alloc_setup();
8931 }
8932 if (i == 0)
8933 fail("Parse succeeded despite failing reallocator");
8934 if (i == max_realloc_count)
8935 fail("Parse failed at maximum reallocation count");
8936 }
8937 END_TEST
8938
8939 /* Test attribute enums in a defaulted attribute forcing pool growth */
START_TEST(test_alloc_realloc_default_attribute)8940 START_TEST(test_alloc_realloc_default_attribute) {
8941 /* Forcing this particular code path is a balancing act. The
8942 * addition of the closing parenthesis and terminal NUL must be
8943 * what pushes the string of enums over the 1024-byte limit,
8944 * otherwise a different code path will pick up the realloc.
8945 */
8946 const char *text
8947 = "<!DOCTYPE doc [\n"
8948 "<!ELEMENT doc EMPTY>\n"
8949 "<!ATTLIST doc a "
8950 /* Each line is 64 characters */
8951 "(ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8952 "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8953 "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8954 "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8955 "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8956 "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8957 "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8958 "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8959 "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8960 "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8961 "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8962 "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8963 "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8964 "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8965 "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8966 "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN)"
8967 " 'ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO'"
8968 ">\n]><doc/>";
8969 int i;
8970 const int max_realloc_count = 10;
8971
8972 for (i = 0; i < max_realloc_count; i++) {
8973 reallocation_count = i;
8974 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
8975 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8976 != XML_STATUS_ERROR)
8977 break;
8978 /* See comment in test_alloc_parse_xdecl() */
8979 alloc_teardown();
8980 alloc_setup();
8981 }
8982 if (i == 0)
8983 fail("Parse succeeded despite failing reallocator");
8984 if (i == max_realloc_count)
8985 fail("Parse failed at maximum reallocation count");
8986 }
8987 END_TEST
8988
8989 /* Test long notation name with dodgy allocator */
START_TEST(test_alloc_notation)8990 START_TEST(test_alloc_notation) {
8991 const char *text
8992 = "<!DOCTYPE doc [\n"
8993 "<!NOTATION "
8994 /* Each line is 64 characters */
8995 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8996 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8997 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8998 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8999 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9000 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9001 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9002 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9003 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9004 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9005 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9006 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9007 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9008 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9009 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9010 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9011 " SYSTEM 'http://example.org/n'>\n"
9012 "<!ENTITY e SYSTEM 'http://example.org/e' NDATA "
9013 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9014 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9015 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9016 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9017 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9018 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9019 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9020 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9021 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9022 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9023 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9024 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9025 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9026 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9027 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9028 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9029 ">\n"
9030 "<!ELEMENT doc EMPTY>\n"
9031 "]>\n<doc/>";
9032 int i;
9033 const int max_alloc_count = 20;
9034
9035 for (i = 0; i < max_alloc_count; i++) {
9036 allocation_count = i;
9037 dummy_handler_flags = 0;
9038 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
9039 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
9040 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9041 != XML_STATUS_ERROR)
9042 break;
9043 /* See comment in test_alloc_parse_xdecl() */
9044 alloc_teardown();
9045 alloc_setup();
9046 }
9047 if (i == 0)
9048 fail("Parse succeeded despite allocation failures");
9049 if (i == max_alloc_count)
9050 fail("Parse failed at maximum allocation count");
9051 if (dummy_handler_flags
9052 != (DUMMY_ENTITY_DECL_HANDLER_FLAG | DUMMY_NOTATION_DECL_HANDLER_FLAG))
9053 fail("Entity declaration handler not called");
9054 }
9055 END_TEST
9056
9057 /* Test public notation with dodgy allocator */
START_TEST(test_alloc_public_notation)9058 START_TEST(test_alloc_public_notation) {
9059 const char *text
9060 = "<!DOCTYPE doc [\n"
9061 "<!NOTATION note PUBLIC '"
9062 /* 64 characters per line */
9063 "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/"
9064 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9065 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9066 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9067 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9068 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9069 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9070 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9071 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9072 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9073 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9074 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9075 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9076 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9077 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9078 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9079 "' 'foo'>\n"
9080 "<!ENTITY e SYSTEM 'http://example.com/e' NDATA note>\n"
9081 "<!ELEMENT doc EMPTY>\n"
9082 "]>\n<doc/>";
9083 int i;
9084 const int max_alloc_count = 20;
9085
9086 for (i = 0; i < max_alloc_count; i++) {
9087 allocation_count = i;
9088 dummy_handler_flags = 0;
9089 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
9090 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9091 != XML_STATUS_ERROR)
9092 break;
9093 /* See comment in test_alloc_parse_xdecl() */
9094 alloc_teardown();
9095 alloc_setup();
9096 }
9097 if (i == 0)
9098 fail("Parse succeeded despite allocation failures");
9099 if (i == max_alloc_count)
9100 fail("Parse failed at maximum allocation count");
9101 if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG)
9102 fail("Notation handler not called");
9103 }
9104 END_TEST
9105
9106 /* Test public notation with dodgy allocator */
START_TEST(test_alloc_system_notation)9107 START_TEST(test_alloc_system_notation) {
9108 const char *text
9109 = "<!DOCTYPE doc [\n"
9110 "<!NOTATION note SYSTEM '"
9111 /* 64 characters per line */
9112 "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/"
9113 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9114 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9115 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9116 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9117 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9118 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9119 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9120 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9121 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9122 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9123 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9124 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9125 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9126 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9127 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9128 "'>\n"
9129 "<!ENTITY e SYSTEM 'http://example.com/e' NDATA note>\n"
9130 "<!ELEMENT doc EMPTY>\n"
9131 "]>\n<doc/>";
9132 int i;
9133 const int max_alloc_count = 20;
9134
9135 for (i = 0; i < max_alloc_count; i++) {
9136 allocation_count = i;
9137 dummy_handler_flags = 0;
9138 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
9139 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9140 != XML_STATUS_ERROR)
9141 break;
9142 /* See comment in test_alloc_parse_xdecl() */
9143 alloc_teardown();
9144 alloc_setup();
9145 }
9146 if (i == 0)
9147 fail("Parse succeeded despite allocation failures");
9148 if (i == max_alloc_count)
9149 fail("Parse failed at maximum allocation count");
9150 if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG)
9151 fail("Notation handler not called");
9152 }
9153 END_TEST
9154
START_TEST(test_alloc_nested_groups)9155 START_TEST(test_alloc_nested_groups) {
9156 const char *text
9157 = "<!DOCTYPE doc [\n"
9158 "<!ELEMENT doc "
9159 /* Sixteen elements per line */
9160 "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,"
9161 "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?"
9162 "))))))))))))))))))))))))))))))))>\n"
9163 "<!ELEMENT e EMPTY>"
9164 "]>\n"
9165 "<doc><e/></doc>";
9166 CharData storage;
9167 int i;
9168 const int max_alloc_count = 20;
9169
9170 for (i = 0; i < max_alloc_count; i++) {
9171 allocation_count = i;
9172 CharData_Init(&storage);
9173 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
9174 XML_SetStartElementHandler(g_parser, record_element_start_handler);
9175 XML_SetUserData(g_parser, &storage);
9176 dummy_handler_flags = 0;
9177 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9178 != XML_STATUS_ERROR)
9179 break;
9180 /* See comment in test_alloc_parse_xdecl() */
9181 alloc_teardown();
9182 alloc_setup();
9183 }
9184
9185 if (i == 0)
9186 fail("Parse succeeded despite failing reallocator");
9187 if (i == max_alloc_count)
9188 fail("Parse failed at maximum reallocation count");
9189 CharData_CheckXMLChars(&storage, XCS("doce"));
9190 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9191 fail("Element handler not fired");
9192 }
9193 END_TEST
9194
START_TEST(test_alloc_realloc_nested_groups)9195 START_TEST(test_alloc_realloc_nested_groups) {
9196 const char *text
9197 = "<!DOCTYPE doc [\n"
9198 "<!ELEMENT doc "
9199 /* Sixteen elements per line */
9200 "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,"
9201 "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?"
9202 "))))))))))))))))))))))))))))))))>\n"
9203 "<!ELEMENT e EMPTY>"
9204 "]>\n"
9205 "<doc><e/></doc>";
9206 CharData storage;
9207 int i;
9208 const int max_realloc_count = 10;
9209
9210 for (i = 0; i < max_realloc_count; i++) {
9211 reallocation_count = i;
9212 CharData_Init(&storage);
9213 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
9214 XML_SetStartElementHandler(g_parser, record_element_start_handler);
9215 XML_SetUserData(g_parser, &storage);
9216 dummy_handler_flags = 0;
9217 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9218 != XML_STATUS_ERROR)
9219 break;
9220 /* See comment in test_alloc_parse_xdecl() */
9221 alloc_teardown();
9222 alloc_setup();
9223 }
9224
9225 if (i == 0)
9226 fail("Parse succeeded despite failing reallocator");
9227 if (i == max_realloc_count)
9228 fail("Parse failed at maximum reallocation count");
9229 CharData_CheckXMLChars(&storage, XCS("doce"));
9230 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9231 fail("Element handler not fired");
9232 }
9233 END_TEST
9234
START_TEST(test_alloc_large_group)9235 START_TEST(test_alloc_large_group) {
9236 const char *text = "<!DOCTYPE doc [\n"
9237 "<!ELEMENT doc ("
9238 "a1|a2|a3|a4|a5|a6|a7|a8|"
9239 "b1|b2|b3|b4|b5|b6|b7|b8|"
9240 "c1|c2|c3|c4|c5|c6|c7|c8|"
9241 "d1|d2|d3|d4|d5|d6|d7|d8|"
9242 "e1"
9243 ")+>\n"
9244 "]>\n"
9245 "<doc>\n"
9246 "<a1/>\n"
9247 "</doc>\n";
9248 int i;
9249 const int max_alloc_count = 50;
9250
9251 for (i = 0; i < max_alloc_count; i++) {
9252 allocation_count = i;
9253 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
9254 dummy_handler_flags = 0;
9255 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9256 != XML_STATUS_ERROR)
9257 break;
9258 /* See comment in test_alloc_parse_xdecl() */
9259 alloc_teardown();
9260 alloc_setup();
9261 }
9262 if (i == 0)
9263 fail("Parse succeeded despite failing allocator");
9264 if (i == max_alloc_count)
9265 fail("Parse failed at maximum allocation count");
9266 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9267 fail("Element handler flag not raised");
9268 }
9269 END_TEST
9270
START_TEST(test_alloc_realloc_group_choice)9271 START_TEST(test_alloc_realloc_group_choice) {
9272 const char *text = "<!DOCTYPE doc [\n"
9273 "<!ELEMENT doc ("
9274 "a1|a2|a3|a4|a5|a6|a7|a8|"
9275 "b1|b2|b3|b4|b5|b6|b7|b8|"
9276 "c1|c2|c3|c4|c5|c6|c7|c8|"
9277 "d1|d2|d3|d4|d5|d6|d7|d8|"
9278 "e1"
9279 ")+>\n"
9280 "]>\n"
9281 "<doc>\n"
9282 "<a1/>\n"
9283 "<b2 attr='foo'>This is a foo</b2>\n"
9284 "<c3></c3>\n"
9285 "</doc>\n";
9286 int i;
9287 const int max_realloc_count = 10;
9288
9289 for (i = 0; i < max_realloc_count; i++) {
9290 reallocation_count = i;
9291 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
9292 dummy_handler_flags = 0;
9293 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9294 != XML_STATUS_ERROR)
9295 break;
9296 /* See comment in test_alloc_parse_xdecl() */
9297 alloc_teardown();
9298 alloc_setup();
9299 }
9300 if (i == 0)
9301 fail("Parse succeeded despite failing reallocator");
9302 if (i == max_realloc_count)
9303 fail("Parse failed at maximum reallocation count");
9304 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9305 fail("Element handler flag not raised");
9306 }
9307 END_TEST
9308
START_TEST(test_alloc_pi_in_epilog)9309 START_TEST(test_alloc_pi_in_epilog) {
9310 const char *text = "<doc></doc>\n"
9311 "<?pi in epilog?>";
9312 int i;
9313 const int max_alloc_count = 15;
9314
9315 for (i = 0; i < max_alloc_count; i++) {
9316 allocation_count = i;
9317 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
9318 dummy_handler_flags = 0;
9319 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9320 != XML_STATUS_ERROR)
9321 break;
9322 /* See comment in test_alloc_parse_xdecl() */
9323 alloc_teardown();
9324 alloc_setup();
9325 }
9326 if (i == 0)
9327 fail("Parse completed despite failing allocator");
9328 if (i == max_alloc_count)
9329 fail("Parse failed at maximum allocation count");
9330 if (dummy_handler_flags != DUMMY_PI_HANDLER_FLAG)
9331 fail("Processing instruction handler not invoked");
9332 }
9333 END_TEST
9334
START_TEST(test_alloc_comment_in_epilog)9335 START_TEST(test_alloc_comment_in_epilog) {
9336 const char *text = "<doc></doc>\n"
9337 "<!-- comment in epilog -->";
9338 int i;
9339 const int max_alloc_count = 15;
9340
9341 for (i = 0; i < max_alloc_count; i++) {
9342 allocation_count = i;
9343 XML_SetCommentHandler(g_parser, dummy_comment_handler);
9344 dummy_handler_flags = 0;
9345 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9346 != XML_STATUS_ERROR)
9347 break;
9348 /* See comment in test_alloc_parse_xdecl() */
9349 alloc_teardown();
9350 alloc_setup();
9351 }
9352 if (i == 0)
9353 fail("Parse completed despite failing allocator");
9354 if (i == max_alloc_count)
9355 fail("Parse failed at maximum allocation count");
9356 if (dummy_handler_flags != DUMMY_COMMENT_HANDLER_FLAG)
9357 fail("Processing instruction handler not invoked");
9358 }
9359 END_TEST
9360
START_TEST(test_alloc_realloc_long_attribute_value)9361 START_TEST(test_alloc_realloc_long_attribute_value) {
9362 const char *text
9363 = "<!DOCTYPE doc [<!ENTITY foo '"
9364 /* Each line is 64 characters */
9365 "This entity will be substituted as an attribute value, and is "
9366 "calculated to be exactly long enough that the terminating NUL "
9367 "that the library adds internally will trigger the string pool to"
9368 "grow. GHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9369 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9370 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9371 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9372 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9373 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9374 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9375 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9376 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9377 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9378 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9379 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9380 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9381 "'>]>\n"
9382 "<doc a='&foo;'></doc>";
9383 int i;
9384 const int max_realloc_count = 10;
9385
9386 for (i = 0; i < max_realloc_count; i++) {
9387 reallocation_count = i;
9388 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9389 != XML_STATUS_ERROR)
9390 break;
9391 /* See comment in test_alloc_parse_xdecl() */
9392 alloc_teardown();
9393 alloc_setup();
9394 }
9395 if (i == 0)
9396 fail("Parse succeeded despite failing reallocator");
9397 if (i == max_realloc_count)
9398 fail("Parse failed at maximum reallocation count");
9399 }
9400 END_TEST
9401
START_TEST(test_alloc_attribute_whitespace)9402 START_TEST(test_alloc_attribute_whitespace) {
9403 const char *text = "<doc a=' '></doc>";
9404 int i;
9405 const int max_alloc_count = 15;
9406
9407 for (i = 0; i < max_alloc_count; i++) {
9408 allocation_count = i;
9409 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9410 != XML_STATUS_ERROR)
9411 break;
9412 /* See comment in test_alloc_parse_xdecl() */
9413 alloc_teardown();
9414 alloc_setup();
9415 }
9416 if (i == 0)
9417 fail("Parse succeeded despite failing allocator");
9418 if (i == max_alloc_count)
9419 fail("Parse failed at maximum allocation count");
9420 }
9421 END_TEST
9422
START_TEST(test_alloc_attribute_predefined_entity)9423 START_TEST(test_alloc_attribute_predefined_entity) {
9424 const char *text = "<doc a='&'></doc>";
9425 int i;
9426 const int max_alloc_count = 15;
9427
9428 for (i = 0; i < max_alloc_count; i++) {
9429 allocation_count = i;
9430 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9431 != XML_STATUS_ERROR)
9432 break;
9433 /* See comment in test_alloc_parse_xdecl() */
9434 alloc_teardown();
9435 alloc_setup();
9436 }
9437 if (i == 0)
9438 fail("Parse succeeded despite failing allocator");
9439 if (i == max_alloc_count)
9440 fail("Parse failed at maximum allocation count");
9441 }
9442 END_TEST
9443
9444 /* Test that a character reference at the end of a suitably long
9445 * default value for an attribute can trigger pool growth, and recovers
9446 * if the allocator fails on it.
9447 */
START_TEST(test_alloc_long_attr_default_with_char_ref)9448 START_TEST(test_alloc_long_attr_default_with_char_ref) {
9449 const char *text
9450 = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '"
9451 /* 64 characters per line */
9452 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9453 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9454 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9455 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9456 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9457 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9458 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9459 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9460 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9461 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9462 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9463 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9464 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9465 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9466 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9467 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHI"
9468 "1'>]>\n"
9469 "<doc/>";
9470 int i;
9471 const int max_alloc_count = 20;
9472
9473 for (i = 0; i < max_alloc_count; i++) {
9474 allocation_count = i;
9475 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9476 != XML_STATUS_ERROR)
9477 break;
9478 /* See comment in test_alloc_parse_xdecl() */
9479 alloc_teardown();
9480 alloc_setup();
9481 }
9482 if (i == 0)
9483 fail("Parse succeeded despite failing allocator");
9484 if (i == max_alloc_count)
9485 fail("Parse failed at maximum allocation count");
9486 }
9487 END_TEST
9488
9489 /* Test that a long character reference substitution triggers a pool
9490 * expansion correctly for an attribute value.
9491 */
START_TEST(test_alloc_long_attr_value)9492 START_TEST(test_alloc_long_attr_value) {
9493 const char *text
9494 = "<!DOCTYPE test [<!ENTITY foo '\n"
9495 /* 64 characters per line */
9496 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9497 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9498 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9499 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9500 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9501 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9502 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9503 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9504 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9505 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9506 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9507 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9508 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9509 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9510 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9511 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9512 "'>]>\n"
9513 "<test a='&foo;'/>";
9514 int i;
9515 const int max_alloc_count = 25;
9516
9517 for (i = 0; i < max_alloc_count; i++) {
9518 allocation_count = i;
9519 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9520 != XML_STATUS_ERROR)
9521 break;
9522 /* See comment in test_alloc_parse_xdecl() */
9523 alloc_teardown();
9524 alloc_setup();
9525 }
9526 if (i == 0)
9527 fail("Parse succeeded despite failing allocator");
9528 if (i == max_alloc_count)
9529 fail("Parse failed at maximum allocation count");
9530 }
9531 END_TEST
9532
9533 /* Test that an error in a nested parameter entity substitution is
9534 * handled correctly. It seems unlikely that the code path being
9535 * exercised can be reached purely by carefully crafted XML, but an
9536 * allocation error in the right place will definitely do it.
9537 */
START_TEST(test_alloc_nested_entities)9538 START_TEST(test_alloc_nested_entities) {
9539 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n"
9540 "<doc />";
9541 ExtFaults test_data
9542 = {"<!ENTITY % pe1 '"
9543 /* 64 characters per line */
9544 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9545 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9546 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9547 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9548 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9549 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9550 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9551 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9552 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9553 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9554 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9555 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9556 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9557 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9558 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9559 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9560 "'>\n"
9561 "<!ENTITY % pe2 '%pe1;'>\n"
9562 "%pe2;",
9563 "Memory Fail not faulted", NULL, XML_ERROR_NO_MEMORY};
9564
9565 /* Causes an allocation error in a nested storeEntityValue() */
9566 allocation_count = 12;
9567 XML_SetUserData(g_parser, &test_data);
9568 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9569 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
9570 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
9571 "Entity allocation failure not noted");
9572 }
9573 END_TEST
9574
START_TEST(test_alloc_realloc_param_entity_newline)9575 START_TEST(test_alloc_realloc_param_entity_newline) {
9576 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
9577 "<doc/>";
9578 char dtd_text[]
9579 = "<!ENTITY % pe '<!ATTLIST doc att CDATA \""
9580 /* 64 characters per line */
9581 "This default value is carefully crafted so that the carriage "
9582 "return right at the end of the entity string causes an internal "
9583 "string pool to have to grow. This allows us to test the alloc "
9584 "failure path from that point. OPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9585 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9586 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9587 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9588 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9589 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9590 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9591 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9592 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9593 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9594 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9595 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9596 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDE"
9597 "\">\n'>"
9598 "%pe;\n";
9599 int i;
9600 const int max_realloc_count = 5;
9601
9602 for (i = 0; i < max_realloc_count; i++) {
9603 reallocation_count = i;
9604 XML_SetUserData(g_parser, dtd_text);
9605 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9606 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9607 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9608 != XML_STATUS_ERROR)
9609 break;
9610 /* See comment in test_alloc_parse_xdecl() */
9611 alloc_teardown();
9612 alloc_setup();
9613 }
9614 if (i == 0)
9615 fail("Parse succeeded despite failing reallocator");
9616 if (i == max_realloc_count)
9617 fail("Parse failed at maximum reallocation count");
9618 }
9619 END_TEST
9620
START_TEST(test_alloc_realloc_ce_extends_pe)9621 START_TEST(test_alloc_realloc_ce_extends_pe) {
9622 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
9623 "<doc/>";
9624 char dtd_text[]
9625 = "<!ENTITY % pe '<!ATTLIST doc att CDATA \""
9626 /* 64 characters per line */
9627 "This default value is carefully crafted so that the character "
9628 "entity at the end causes an internal string pool to have to "
9629 "grow. This allows us to test the allocation failure path from "
9630 "that point onwards. EFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9631 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9632 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9633 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9634 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9635 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9636 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9637 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9638 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9639 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9640 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9641 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9642 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGQ"
9643 "\">\n'>"
9644 "%pe;\n";
9645 int i;
9646 const int max_realloc_count = 5;
9647
9648 for (i = 0; i < max_realloc_count; i++) {
9649 reallocation_count = i;
9650 XML_SetUserData(g_parser, dtd_text);
9651 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9652 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9653 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9654 != XML_STATUS_ERROR)
9655 break;
9656 /* See comment in test_alloc_parse_xdecl() */
9657 alloc_teardown();
9658 alloc_setup();
9659 }
9660 if (i == 0)
9661 fail("Parse succeeded despite failing reallocator");
9662 if (i == max_realloc_count)
9663 fail("Parse failed at maximum reallocation count");
9664 }
9665 END_TEST
9666
START_TEST(test_alloc_realloc_attributes)9667 START_TEST(test_alloc_realloc_attributes) {
9668 const char *text = "<!DOCTYPE doc [\n"
9669 " <!ATTLIST doc\n"
9670 " a1 (a|b|c) 'a'\n"
9671 " a2 (foo|bar) #IMPLIED\n"
9672 " a3 NMTOKEN #IMPLIED\n"
9673 " a4 NMTOKENS #IMPLIED\n"
9674 " a5 ID #IMPLIED\n"
9675 " a6 IDREF #IMPLIED\n"
9676 " a7 IDREFS #IMPLIED\n"
9677 " a8 ENTITY #IMPLIED\n"
9678 " a9 ENTITIES #IMPLIED\n"
9679 " a10 CDATA #IMPLIED\n"
9680 " >]>\n"
9681 "<doc>wombat</doc>\n";
9682 int i;
9683 const int max_realloc_count = 5;
9684
9685 for (i = 0; i < max_realloc_count; i++) {
9686 reallocation_count = i;
9687 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9688 != XML_STATUS_ERROR)
9689 break;
9690 /* See comment in test_alloc_parse_xdecl() */
9691 alloc_teardown();
9692 alloc_setup();
9693 }
9694
9695 if (i == 0)
9696 fail("Parse succeeded despite failing reallocator");
9697 if (i == max_realloc_count)
9698 fail("Parse failed at maximum reallocation count");
9699 }
9700 END_TEST
9701
START_TEST(test_alloc_long_doc_name)9702 START_TEST(test_alloc_long_doc_name) {
9703 const char *text =
9704 /* 64 characters per line */
9705 "<LongRootElementNameThatWillCauseTheNextAllocationToExpandTheStr"
9706 "ingPoolForTheDTDQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9707 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9708 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9709 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9710 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9711 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9712 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9713 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9714 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9715 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9716 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9717 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9718 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9719 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9720 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9721 " a='1'/>";
9722 int i;
9723 const int max_alloc_count = 20;
9724
9725 for (i = 0; i < max_alloc_count; i++) {
9726 allocation_count = i;
9727 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9728 != XML_STATUS_ERROR)
9729 break;
9730 /* See comment in test_alloc_parse_xdecl() */
9731 alloc_teardown();
9732 alloc_setup();
9733 }
9734 if (i == 0)
9735 fail("Parsing worked despite failing reallocations");
9736 else if (i == max_alloc_count)
9737 fail("Parsing failed even at max reallocation count");
9738 }
9739 END_TEST
9740
START_TEST(test_alloc_long_base)9741 START_TEST(test_alloc_long_base) {
9742 const char *text = "<!DOCTYPE doc [\n"
9743 " <!ENTITY e SYSTEM 'foo'>\n"
9744 "]>\n"
9745 "<doc>&e;</doc>";
9746 char entity_text[] = "Hello world";
9747 const XML_Char *base =
9748 /* 64 characters per line */
9749 /* clang-format off */
9750 XCS("LongBaseURI/that/will/overflow/an/internal/buffer/and/cause/it/t")
9751 XCS("o/have/to/grow/PQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9752 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9753 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9754 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9755 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9756 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9757 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9758 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9759 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9760 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9761 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9762 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9763 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9764 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9765 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/");
9766 /* clang-format on */
9767 int i;
9768 const int max_alloc_count = 25;
9769
9770 for (i = 0; i < max_alloc_count; i++) {
9771 allocation_count = i;
9772 XML_SetUserData(g_parser, entity_text);
9773 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9774 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9775 if (XML_SetBase(g_parser, base) == XML_STATUS_ERROR) {
9776 XML_ParserReset(g_parser, NULL);
9777 continue;
9778 }
9779 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9780 != XML_STATUS_ERROR)
9781 break;
9782 /* See comment in test_alloc_parse_xdecl() */
9783 alloc_teardown();
9784 alloc_setup();
9785 }
9786 if (i == 0)
9787 fail("Parsing worked despite failing allocations");
9788 else if (i == max_alloc_count)
9789 fail("Parsing failed even at max allocation count");
9790 }
9791 END_TEST
9792
START_TEST(test_alloc_long_public_id)9793 START_TEST(test_alloc_long_public_id) {
9794 const char *text
9795 = "<!DOCTYPE doc [\n"
9796 " <!ENTITY e PUBLIC '"
9797 /* 64 characters per line */
9798 "LongPublicIDThatShouldResultInAnInternalStringPoolGrowingAtASpec"
9799 "ificMomentKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9800 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9801 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9802 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9803 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9804 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9805 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9806 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9807 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9808 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9809 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9810 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9811 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9812 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9813 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9814 "' 'bar'>\n"
9815 "]>\n"
9816 "<doc>&e;</doc>";
9817 char entity_text[] = "Hello world";
9818 int i;
9819 const int max_alloc_count = 40;
9820
9821 for (i = 0; i < max_alloc_count; i++) {
9822 allocation_count = i;
9823 XML_SetUserData(g_parser, entity_text);
9824 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9825 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9826 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9827 != XML_STATUS_ERROR)
9828 break;
9829 /* See comment in test_alloc_parse_xdecl() */
9830 alloc_teardown();
9831 alloc_setup();
9832 }
9833 if (i == 0)
9834 fail("Parsing worked despite failing allocations");
9835 else if (i == max_alloc_count)
9836 fail("Parsing failed even at max allocation count");
9837 }
9838 END_TEST
9839
START_TEST(test_alloc_long_entity_value)9840 START_TEST(test_alloc_long_entity_value) {
9841 const char *text
9842 = "<!DOCTYPE doc [\n"
9843 " <!ENTITY e1 '"
9844 /* 64 characters per line */
9845 "Long entity value that should provoke a string pool to grow whil"
9846 "e setting up to parse the external entity below. xyz0123456789AB"
9847 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9848 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9849 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9850 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9851 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9852 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9853 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9854 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9855 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9856 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9857 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9858 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9859 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9860 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9861 "'>\n"
9862 " <!ENTITY e2 SYSTEM 'bar'>\n"
9863 "]>\n"
9864 "<doc>&e2;</doc>";
9865 char entity_text[] = "Hello world";
9866 int i;
9867 const int max_alloc_count = 40;
9868
9869 for (i = 0; i < max_alloc_count; i++) {
9870 allocation_count = i;
9871 XML_SetUserData(g_parser, entity_text);
9872 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9873 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9874 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9875 != XML_STATUS_ERROR)
9876 break;
9877 /* See comment in test_alloc_parse_xdecl() */
9878 alloc_teardown();
9879 alloc_setup();
9880 }
9881 if (i == 0)
9882 fail("Parsing worked despite failing allocations");
9883 else if (i == max_alloc_count)
9884 fail("Parsing failed even at max allocation count");
9885 }
9886 END_TEST
9887
START_TEST(test_alloc_long_notation)9888 START_TEST(test_alloc_long_notation) {
9889 const char *text
9890 = "<!DOCTYPE doc [\n"
9891 " <!NOTATION note SYSTEM '"
9892 /* 64 characters per line */
9893 "ALongNotationNameThatShouldProvokeStringPoolGrowthWhileCallingAn"
9894 "ExternalEntityParserUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9895 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9896 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9897 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9898 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9899 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9900 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9901 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9902 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9903 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9904 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9905 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9906 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9907 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9908 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9909 "'>\n"
9910 " <!ENTITY e1 SYSTEM 'foo' NDATA "
9911 /* 64 characters per line */
9912 "ALongNotationNameThatShouldProvokeStringPoolGrowthWhileCallingAn"
9913 "ExternalEntityParserUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9914 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9915 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9916 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9917 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9918 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9919 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9920 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9921 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9922 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9923 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9924 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9925 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9926 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9927 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9928 ">\n"
9929 " <!ENTITY e2 SYSTEM 'bar'>\n"
9930 "]>\n"
9931 "<doc>&e2;</doc>";
9932 ExtOption options[]
9933 = {{XCS("foo"), "Entity Foo"}, {XCS("bar"), "Entity Bar"}, {NULL, NULL}};
9934 int i;
9935 const int max_alloc_count = 40;
9936
9937 for (i = 0; i < max_alloc_count; i++) {
9938 allocation_count = i;
9939 XML_SetUserData(g_parser, options);
9940 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9941 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
9942 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9943 != XML_STATUS_ERROR)
9944 break;
9945
9946 /* See comment in test_alloc_parse_xdecl() */
9947 alloc_teardown();
9948 alloc_setup();
9949 }
9950 if (i == 0)
9951 fail("Parsing worked despite failing allocations");
9952 else if (i == max_alloc_count)
9953 fail("Parsing failed even at max allocation count");
9954 }
9955 END_TEST
9956
9957 static void
nsalloc_setup(void)9958 nsalloc_setup(void) {
9959 XML_Memory_Handling_Suite memsuite = {duff_allocator, duff_reallocator, free};
9960 XML_Char ns_sep[2] = {' ', '\0'};
9961
9962 /* Ensure the parser creation will go through */
9963 allocation_count = ALLOC_ALWAYS_SUCCEED;
9964 reallocation_count = REALLOC_ALWAYS_SUCCEED;
9965 g_parser = XML_ParserCreate_MM(NULL, &memsuite, ns_sep);
9966 if (g_parser == NULL)
9967 fail("Parser not created");
9968 }
9969
9970 static void
nsalloc_teardown(void)9971 nsalloc_teardown(void) {
9972 basic_teardown();
9973 }
9974
9975 /* Test the effects of allocation failure in simple namespace parsing.
9976 * Based on test_ns_default_with_empty_uri()
9977 */
START_TEST(test_nsalloc_xmlns)9978 START_TEST(test_nsalloc_xmlns) {
9979 const char *text = "<doc xmlns='http://example.org/'>\n"
9980 " <e xmlns=''/>\n"
9981 "</doc>";
9982 unsigned int i;
9983 const unsigned int max_alloc_count = 30;
9984
9985 for (i = 0; i < max_alloc_count; i++) {
9986 allocation_count = i;
9987 /* Exercise more code paths with a default handler */
9988 XML_SetDefaultHandler(g_parser, dummy_default_handler);
9989 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9990 != XML_STATUS_ERROR)
9991 break;
9992 /* Resetting the parser is insufficient, because some memory
9993 * allocations are cached within the parser. Instead we use
9994 * the teardown and setup routines to ensure that we have the
9995 * right sort of parser back in our hands.
9996 */
9997 nsalloc_teardown();
9998 nsalloc_setup();
9999 }
10000 if (i == 0)
10001 fail("Parsing worked despite failing allocations");
10002 else if (i == max_alloc_count)
10003 fail("Parsing failed even at maximum allocation count");
10004 }
10005 END_TEST
10006
10007 /* Test XML_ParseBuffer interface with namespace and a dicky allocator */
START_TEST(test_nsalloc_parse_buffer)10008 START_TEST(test_nsalloc_parse_buffer) {
10009 const char *text = "<doc>Hello</doc>";
10010 void *buffer;
10011
10012 /* Try a parse before the start of the world */
10013 /* (Exercises new code path) */
10014 if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_ERROR)
10015 fail("Pre-init XML_ParseBuffer not faulted");
10016 if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_BUFFER)
10017 fail("Pre-init XML_ParseBuffer faulted for wrong reason");
10018
10019 buffer = XML_GetBuffer(g_parser, 1 /* any small number greater than 0 */);
10020 if (buffer == NULL)
10021 fail("Could not acquire parse buffer");
10022
10023 allocation_count = 0;
10024 if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_ERROR)
10025 fail("Pre-init XML_ParseBuffer not faulted");
10026 if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_MEMORY)
10027 fail("Pre-init XML_ParseBuffer faulted for wrong reason");
10028
10029 /* Now with actual memory allocation */
10030 allocation_count = ALLOC_ALWAYS_SUCCEED;
10031 if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_OK)
10032 xml_failure(g_parser);
10033
10034 /* Check that resuming an unsuspended parser is faulted */
10035 if (XML_ResumeParser(g_parser) != XML_STATUS_ERROR)
10036 fail("Resuming unsuspended parser not faulted");
10037 if (XML_GetErrorCode(g_parser) != XML_ERROR_NOT_SUSPENDED)
10038 xml_failure(g_parser);
10039
10040 /* Get the parser into suspended state */
10041 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
10042 resumable = XML_TRUE;
10043 buffer = XML_GetBuffer(g_parser, (int)strlen(text));
10044 if (buffer == NULL)
10045 fail("Could not acquire parse buffer");
10046 assert(buffer != NULL);
10047 memcpy(buffer, text, strlen(text));
10048 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE)
10049 != XML_STATUS_SUSPENDED)
10050 xml_failure(g_parser);
10051 if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE)
10052 xml_failure(g_parser);
10053 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE)
10054 != XML_STATUS_ERROR)
10055 fail("Suspended XML_ParseBuffer not faulted");
10056 if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED)
10057 xml_failure(g_parser);
10058 if (XML_GetBuffer(g_parser, (int)strlen(text)) != NULL)
10059 fail("Suspended XML_GetBuffer not faulted");
10060
10061 /* Get it going again and complete the world */
10062 XML_SetCharacterDataHandler(g_parser, NULL);
10063 if (XML_ResumeParser(g_parser) != XML_STATUS_OK)
10064 xml_failure(g_parser);
10065 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE)
10066 != XML_STATUS_ERROR)
10067 fail("Post-finishing XML_ParseBuffer not faulted");
10068 if (XML_GetErrorCode(g_parser) != XML_ERROR_FINISHED)
10069 xml_failure(g_parser);
10070 if (XML_GetBuffer(g_parser, (int)strlen(text)) != NULL)
10071 fail("Post-finishing XML_GetBuffer not faulted");
10072 }
10073 END_TEST
10074
10075 /* Check handling of long prefix names (pool growth) */
START_TEST(test_nsalloc_long_prefix)10076 START_TEST(test_nsalloc_long_prefix) {
10077 const char *text
10078 = "<"
10079 /* 64 characters per line */
10080 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10081 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10082 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10083 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10084 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10085 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10086 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10087 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10088 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10089 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10090 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10091 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10092 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10093 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10094 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10095 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10096 ":foo xmlns:"
10097 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10098 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10099 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10100 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10101 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10102 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10103 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10104 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10105 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10106 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10107 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10108 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10109 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10110 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10111 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10112 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10113 "='http://example.org/'>"
10114 "</"
10115 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10116 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10117 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10118 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10119 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10120 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10121 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10122 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10123 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10124 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10125 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10126 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10127 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10128 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10129 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10130 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10131 ":foo>";
10132 int i;
10133 const int max_alloc_count = 40;
10134
10135 for (i = 0; i < max_alloc_count; i++) {
10136 allocation_count = i;
10137 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10138 != XML_STATUS_ERROR)
10139 break;
10140 /* See comment in test_nsalloc_xmlns() */
10141 nsalloc_teardown();
10142 nsalloc_setup();
10143 }
10144 if (i == 0)
10145 fail("Parsing worked despite failing allocations");
10146 else if (i == max_alloc_count)
10147 fail("Parsing failed even at max allocation count");
10148 }
10149 END_TEST
10150
10151 /* Check handling of long uri names (pool growth) */
START_TEST(test_nsalloc_long_uri)10152 START_TEST(test_nsalloc_long_uri) {
10153 const char *text
10154 = "<foo:e xmlns:foo='http://example.org/"
10155 /* 64 characters per line */
10156 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10157 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10158 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10159 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10160 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10161 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10162 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10163 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10164 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10165 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10166 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10167 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10168 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10169 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10170 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10171 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10172 "' bar:a='12'\n"
10173 "xmlns:bar='http://example.org/"
10174 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10175 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10176 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10177 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10178 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10179 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10180 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10181 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10182 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10183 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10184 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10185 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10186 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10187 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10188 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10189 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10190 "'>"
10191 "</foo:e>";
10192 int i;
10193 const int max_alloc_count = 40;
10194
10195 for (i = 0; i < max_alloc_count; i++) {
10196 allocation_count = i;
10197 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10198 != XML_STATUS_ERROR)
10199 break;
10200 /* See comment in test_nsalloc_xmlns() */
10201 nsalloc_teardown();
10202 nsalloc_setup();
10203 }
10204 if (i == 0)
10205 fail("Parsing worked despite failing allocations");
10206 else if (i == max_alloc_count)
10207 fail("Parsing failed even at max allocation count");
10208 }
10209 END_TEST
10210
10211 /* Test handling of long attribute names with prefixes */
START_TEST(test_nsalloc_long_attr)10212 START_TEST(test_nsalloc_long_attr) {
10213 const char *text
10214 = "<foo:e xmlns:foo='http://example.org/' bar:"
10215 /* 64 characters per line */
10216 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10217 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10218 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10219 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10220 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10221 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10222 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10223 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10224 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10225 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10226 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10227 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10228 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10229 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10230 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10231 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10232 "='12'\n"
10233 "xmlns:bar='http://example.org/'>"
10234 "</foo:e>";
10235 int i;
10236 const int max_alloc_count = 40;
10237
10238 for (i = 0; i < max_alloc_count; i++) {
10239 allocation_count = i;
10240 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10241 != XML_STATUS_ERROR)
10242 break;
10243 /* See comment in test_nsalloc_xmlns() */
10244 nsalloc_teardown();
10245 nsalloc_setup();
10246 }
10247 if (i == 0)
10248 fail("Parsing worked despite failing allocations");
10249 else if (i == max_alloc_count)
10250 fail("Parsing failed even at max allocation count");
10251 }
10252 END_TEST
10253
10254 /* Test handling of an attribute name with a long namespace prefix */
START_TEST(test_nsalloc_long_attr_prefix)10255 START_TEST(test_nsalloc_long_attr_prefix) {
10256 const char *text
10257 = "<foo:e xmlns:foo='http://example.org/' "
10258 /* 64 characters per line */
10259 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10260 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10261 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10262 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10263 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10264 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10265 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10266 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10267 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10268 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10269 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10270 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10271 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10272 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10273 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10274 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10275 ":a='12'\n"
10276 "xmlns:"
10277 /* 64 characters per line */
10278 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10279 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10280 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10281 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10282 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10283 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10284 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10285 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10286 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10287 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10288 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10289 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10290 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10291 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10292 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10293 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10294 "='http://example.org/'>"
10295 "</foo:e>";
10296 const XML_Char *elemstr[] = {
10297 /* clang-format off */
10298 XCS("http://example.org/ e foo"),
10299 XCS("http://example.org/ a ")
10300 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10301 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10302 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10303 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10304 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10305 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10306 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10307 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10308 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10309 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10310 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10311 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10312 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10313 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10314 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10315 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10316 /* clang-format on */
10317 };
10318 int i;
10319 const int max_alloc_count = 40;
10320
10321 for (i = 0; i < max_alloc_count; i++) {
10322 allocation_count = i;
10323 XML_SetReturnNSTriplet(g_parser, XML_TRUE);
10324 XML_SetUserData(g_parser, (void *)elemstr);
10325 XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
10326 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10327 != XML_STATUS_ERROR)
10328 break;
10329 /* See comment in test_nsalloc_xmlns() */
10330 nsalloc_teardown();
10331 nsalloc_setup();
10332 }
10333 if (i == 0)
10334 fail("Parsing worked despite failing allocations");
10335 else if (i == max_alloc_count)
10336 fail("Parsing failed even at max allocation count");
10337 }
10338 END_TEST
10339
10340 /* Test attribute handling in the face of a dodgy reallocator */
START_TEST(test_nsalloc_realloc_attributes)10341 START_TEST(test_nsalloc_realloc_attributes) {
10342 const char *text = "<foo:e xmlns:foo='http://example.org/' bar:a='12'\n"
10343 " xmlns:bar='http://example.org/'>"
10344 "</foo:e>";
10345 int i;
10346 const int max_realloc_count = 10;
10347
10348 for (i = 0; i < max_realloc_count; i++) {
10349 reallocation_count = i;
10350 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10351 != XML_STATUS_ERROR)
10352 break;
10353 /* See comment in test_nsalloc_xmlns() */
10354 nsalloc_teardown();
10355 nsalloc_setup();
10356 }
10357 if (i == 0)
10358 fail("Parsing worked despite failing reallocations");
10359 else if (i == max_realloc_count)
10360 fail("Parsing failed at max reallocation count");
10361 }
10362 END_TEST
10363
10364 /* Test long element names with namespaces under a failing allocator */
START_TEST(test_nsalloc_long_element)10365 START_TEST(test_nsalloc_long_element) {
10366 const char *text
10367 = "<foo:thisisalongenoughelementnametotriggerareallocation\n"
10368 " xmlns:foo='http://example.org/' bar:a='12'\n"
10369 " xmlns:bar='http://example.org/'>"
10370 "</foo:thisisalongenoughelementnametotriggerareallocation>";
10371 const XML_Char *elemstr[]
10372 = {XCS("http://example.org/")
10373 XCS(" thisisalongenoughelementnametotriggerareallocation foo"),
10374 XCS("http://example.org/ a bar")};
10375 int i;
10376 const int max_alloc_count = 30;
10377
10378 for (i = 0; i < max_alloc_count; i++) {
10379 allocation_count = i;
10380 XML_SetReturnNSTriplet(g_parser, XML_TRUE);
10381 XML_SetUserData(g_parser, (void *)elemstr);
10382 XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
10383 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10384 != XML_STATUS_ERROR)
10385 break;
10386 /* See comment in test_nsalloc_xmlns() */
10387 nsalloc_teardown();
10388 nsalloc_setup();
10389 }
10390 if (i == 0)
10391 fail("Parsing worked despite failing reallocations");
10392 else if (i == max_alloc_count)
10393 fail("Parsing failed at max reallocation count");
10394 }
10395 END_TEST
10396
10397 /* Test the effects of reallocation failure when reassigning a
10398 * binding.
10399 *
10400 * XML_ParserReset does not free the BINDING structures used by a
10401 * parser, but instead adds them to an internal free list to be reused
10402 * as necessary. Likewise the URI buffers allocated for the binding
10403 * aren't freed, but kept attached to their existing binding. If the
10404 * new binding has a longer URI, it will need reallocation. This test
10405 * provokes that reallocation, and tests the control path if it fails.
10406 */
START_TEST(test_nsalloc_realloc_binding_uri)10407 START_TEST(test_nsalloc_realloc_binding_uri) {
10408 const char *first = "<doc xmlns='http://example.org/'>\n"
10409 " <e xmlns='' />\n"
10410 "</doc>";
10411 const char *second
10412 = "<doc xmlns='http://example.org/long/enough/URI/to/reallocate/'>\n"
10413 " <e xmlns='' />\n"
10414 "</doc>";
10415 unsigned i;
10416 const unsigned max_realloc_count = 10;
10417
10418 /* First, do a full parse that will leave bindings around */
10419 if (_XML_Parse_SINGLE_BYTES(g_parser, first, (int)strlen(first), XML_TRUE)
10420 == XML_STATUS_ERROR)
10421 xml_failure(g_parser);
10422
10423 /* Now repeat with a longer URI and a duff reallocator */
10424 for (i = 0; i < max_realloc_count; i++) {
10425 XML_ParserReset(g_parser, NULL);
10426 reallocation_count = i;
10427 if (_XML_Parse_SINGLE_BYTES(g_parser, second, (int)strlen(second), XML_TRUE)
10428 != XML_STATUS_ERROR)
10429 break;
10430 }
10431 if (i == 0)
10432 fail("Parsing worked despite failing reallocation");
10433 else if (i == max_realloc_count)
10434 fail("Parsing failed at max reallocation count");
10435 }
10436 END_TEST
10437
10438 /* Check handling of long prefix names (pool growth) */
START_TEST(test_nsalloc_realloc_long_prefix)10439 START_TEST(test_nsalloc_realloc_long_prefix) {
10440 const char *text
10441 = "<"
10442 /* 64 characters per line */
10443 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10444 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10445 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10446 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10447 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10448 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10449 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10450 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10451 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10452 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10453 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10454 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10455 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10456 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10457 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10458 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10459 ":foo xmlns:"
10460 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10461 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10462 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10463 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10464 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10465 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10466 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10467 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10468 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10469 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10470 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10471 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10472 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10473 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10474 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10475 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10476 "='http://example.org/'>"
10477 "</"
10478 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10479 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10480 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10481 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10482 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10483 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10484 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10485 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10486 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10487 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10488 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10489 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10490 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10491 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10492 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10493 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10494 ":foo>";
10495 int i;
10496 const int max_realloc_count = 12;
10497
10498 for (i = 0; i < max_realloc_count; i++) {
10499 reallocation_count = i;
10500 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10501 != XML_STATUS_ERROR)
10502 break;
10503 /* See comment in test_nsalloc_xmlns() */
10504 nsalloc_teardown();
10505 nsalloc_setup();
10506 }
10507 if (i == 0)
10508 fail("Parsing worked despite failing reallocations");
10509 else if (i == max_realloc_count)
10510 fail("Parsing failed even at max reallocation count");
10511 }
10512 END_TEST
10513
10514 /* Check handling of even long prefix names (different code path) */
START_TEST(test_nsalloc_realloc_longer_prefix)10515 START_TEST(test_nsalloc_realloc_longer_prefix) {
10516 const char *text
10517 = "<"
10518 /* 64 characters per line */
10519 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10520 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10521 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10522 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10523 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10524 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10525 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10526 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10527 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10528 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10529 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10530 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10531 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10532 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10533 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10534 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10535 "Q:foo xmlns:"
10536 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10537 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10538 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10539 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10540 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10541 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10542 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10543 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10544 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10545 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10546 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10547 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10548 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10549 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10550 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10551 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10552 "Q='http://example.org/'>"
10553 "</"
10554 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10555 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10556 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10557 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10558 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10559 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10560 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10561 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10562 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10563 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10564 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10565 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10566 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10567 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10568 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10569 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10570 "Q:foo>";
10571 int i;
10572 const int max_realloc_count = 12;
10573
10574 for (i = 0; i < max_realloc_count; i++) {
10575 reallocation_count = i;
10576 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10577 != XML_STATUS_ERROR)
10578 break;
10579 /* See comment in test_nsalloc_xmlns() */
10580 nsalloc_teardown();
10581 nsalloc_setup();
10582 }
10583 if (i == 0)
10584 fail("Parsing worked despite failing reallocations");
10585 else if (i == max_realloc_count)
10586 fail("Parsing failed even at max reallocation count");
10587 }
10588 END_TEST
10589
START_TEST(test_nsalloc_long_namespace)10590 START_TEST(test_nsalloc_long_namespace) {
10591 const char *text1
10592 = "<"
10593 /* 64 characters per line */
10594 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10595 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10596 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10597 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10598 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10599 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10600 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10601 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10602 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10603 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10604 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10605 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10606 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10607 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10608 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10609 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10610 ":e xmlns:"
10611 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10612 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10613 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10614 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10615 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10616 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10617 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10618 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10619 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10620 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10621 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10622 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10623 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10624 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10625 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10626 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10627 "='http://example.org/'>\n";
10628 const char *text2
10629 = "<"
10630 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10631 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10632 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10633 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10634 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10635 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10636 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10637 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10638 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10639 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10640 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10641 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10642 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10643 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10644 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10645 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10646 ":f "
10647 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10648 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10649 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10650 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10651 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10652 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10653 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10654 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10655 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10656 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10657 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10658 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10659 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10660 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10661 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10662 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10663 ":attr='foo'/>\n"
10664 "</"
10665 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10666 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10667 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10668 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10669 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10670 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10671 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10672 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10673 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10674 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10675 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10676 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10677 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10678 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10679 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10680 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10681 ":e>";
10682 int i;
10683 const int max_alloc_count = 40;
10684
10685 for (i = 0; i < max_alloc_count; i++) {
10686 allocation_count = i;
10687 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
10688 != XML_STATUS_ERROR
10689 && _XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2),
10690 XML_TRUE)
10691 != XML_STATUS_ERROR)
10692 break;
10693 /* See comment in test_nsalloc_xmlns() */
10694 nsalloc_teardown();
10695 nsalloc_setup();
10696 }
10697 if (i == 0)
10698 fail("Parsing worked despite failing allocations");
10699 else if (i == max_alloc_count)
10700 fail("Parsing failed even at max allocation count");
10701 }
10702 END_TEST
10703
10704 /* Using a slightly shorter namespace name provokes allocations in
10705 * slightly different places in the code.
10706 */
START_TEST(test_nsalloc_less_long_namespace)10707 START_TEST(test_nsalloc_less_long_namespace) {
10708 const char *text
10709 = "<"
10710 /* 64 characters per line */
10711 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10712 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10713 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10714 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10715 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10716 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10717 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10718 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10719 ":e xmlns:"
10720 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10721 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10722 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10723 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10724 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10725 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10726 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10727 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10728 "='http://example.org/'>\n"
10729 "<"
10730 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10731 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10732 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10733 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10734 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10735 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10736 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10737 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10738 ":f "
10739 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10740 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10741 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10742 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10743 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10744 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10745 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10746 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10747 ":att='foo'/>\n"
10748 "</"
10749 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10750 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10751 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10752 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10753 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10754 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10755 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10756 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10757 ":e>";
10758 int i;
10759 const int max_alloc_count = 40;
10760
10761 for (i = 0; i < max_alloc_count; i++) {
10762 allocation_count = i;
10763 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10764 != XML_STATUS_ERROR)
10765 break;
10766 /* See comment in test_nsalloc_xmlns() */
10767 nsalloc_teardown();
10768 nsalloc_setup();
10769 }
10770 if (i == 0)
10771 fail("Parsing worked despite failing allocations");
10772 else if (i == max_alloc_count)
10773 fail("Parsing failed even at max allocation count");
10774 }
10775 END_TEST
10776
START_TEST(test_nsalloc_long_context)10777 START_TEST(test_nsalloc_long_context) {
10778 const char *text
10779 = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10780 " <!ATTLIST doc baz ID #REQUIRED>\n"
10781 " <!ENTITY en SYSTEM 'bar'>\n"
10782 "]>\n"
10783 "<doc xmlns='http://example.org/"
10784 /* 64 characters per line */
10785 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10786 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10787 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10788 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10789 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10790 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10791 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10792 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10793 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10794 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10795 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10796 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10797 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10798 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10799 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10800 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKL"
10801 "' baz='2'>\n"
10802 "&en;"
10803 "</doc>";
10804 ExtOption options[] = {
10805 {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}};
10806 int i;
10807 const int max_alloc_count = 70;
10808
10809 for (i = 0; i < max_alloc_count; i++) {
10810 allocation_count = i;
10811 XML_SetUserData(g_parser, options);
10812 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
10813 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
10814 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10815 != XML_STATUS_ERROR)
10816 break;
10817
10818 /* See comment in test_nsalloc_xmlns() */
10819 nsalloc_teardown();
10820 nsalloc_setup();
10821 }
10822 if (i == 0)
10823 fail("Parsing worked despite failing allocations");
10824 else if (i == max_alloc_count)
10825 fail("Parsing failed even at max allocation count");
10826 }
10827 END_TEST
10828
10829 /* This function is void; it will throw a fail() on error, so if it
10830 * returns normally it must have succeeded.
10831 */
10832 static void
context_realloc_test(const char * text)10833 context_realloc_test(const char *text) {
10834 ExtOption options[] = {
10835 {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}};
10836 int i;
10837 const int max_realloc_count = 6;
10838
10839 for (i = 0; i < max_realloc_count; i++) {
10840 reallocation_count = i;
10841 XML_SetUserData(g_parser, options);
10842 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
10843 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
10844 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10845 != XML_STATUS_ERROR)
10846 break;
10847 /* See comment in test_nsalloc_xmlns() */
10848 nsalloc_teardown();
10849 nsalloc_setup();
10850 }
10851 if (i == 0)
10852 fail("Parsing worked despite failing reallocations");
10853 else if (i == max_realloc_count)
10854 fail("Parsing failed even at max reallocation count");
10855 }
10856
START_TEST(test_nsalloc_realloc_long_context)10857 START_TEST(test_nsalloc_realloc_long_context) {
10858 const char *text
10859 = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10860 " <!ENTITY en SYSTEM 'bar'>\n"
10861 "]>\n"
10862 "<doc xmlns='http://example.org/"
10863 /* 64 characters per line */
10864 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10865 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10866 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10867 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10868 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10869 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10870 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10871 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10872 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10873 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10874 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10875 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10876 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10877 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10878 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10879 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKL"
10880 "'>\n"
10881 "&en;"
10882 "</doc>";
10883
10884 context_realloc_test(text);
10885 }
10886 END_TEST
10887
START_TEST(test_nsalloc_realloc_long_context_2)10888 START_TEST(test_nsalloc_realloc_long_context_2) {
10889 const char *text
10890 = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10891 " <!ENTITY en SYSTEM 'bar'>\n"
10892 "]>\n"
10893 "<doc xmlns='http://example.org/"
10894 /* 64 characters per line */
10895 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10896 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10897 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10898 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10899 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10900 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10901 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10902 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10903 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10904 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10905 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10906 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10907 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10908 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10909 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10910 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJK"
10911 "'>\n"
10912 "&en;"
10913 "</doc>";
10914
10915 context_realloc_test(text);
10916 }
10917 END_TEST
10918
START_TEST(test_nsalloc_realloc_long_context_3)10919 START_TEST(test_nsalloc_realloc_long_context_3) {
10920 const char *text
10921 = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10922 " <!ENTITY en SYSTEM 'bar'>\n"
10923 "]>\n"
10924 "<doc xmlns='http://example.org/"
10925 /* 64 characters per line */
10926 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10927 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10928 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10929 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10930 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10931 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10932 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10933 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10934 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10935 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10936 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10937 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10938 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10939 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10940 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10941 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGH"
10942 "'>\n"
10943 "&en;"
10944 "</doc>";
10945
10946 context_realloc_test(text);
10947 }
10948 END_TEST
10949
START_TEST(test_nsalloc_realloc_long_context_4)10950 START_TEST(test_nsalloc_realloc_long_context_4) {
10951 const char *text
10952 = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10953 " <!ENTITY en SYSTEM 'bar'>\n"
10954 "]>\n"
10955 "<doc xmlns='http://example.org/"
10956 /* 64 characters per line */
10957 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10958 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10959 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10960 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10961 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10962 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10963 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10964 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10965 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10966 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10967 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10968 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10969 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10970 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10971 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10972 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO"
10973 "'>\n"
10974 "&en;"
10975 "</doc>";
10976
10977 context_realloc_test(text);
10978 }
10979 END_TEST
10980
START_TEST(test_nsalloc_realloc_long_context_5)10981 START_TEST(test_nsalloc_realloc_long_context_5) {
10982 const char *text
10983 = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10984 " <!ENTITY en SYSTEM 'bar'>\n"
10985 "]>\n"
10986 "<doc xmlns='http://example.org/"
10987 /* 64 characters per line */
10988 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10989 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10990 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10991 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10992 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10993 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10994 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10995 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10996 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10997 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10998 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10999 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11000 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11001 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11002 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11003 "ABC"
11004 "'>\n"
11005 "&en;"
11006 "</doc>";
11007
11008 context_realloc_test(text);
11009 }
11010 END_TEST
11011
START_TEST(test_nsalloc_realloc_long_context_6)11012 START_TEST(test_nsalloc_realloc_long_context_6) {
11013 const char *text
11014 = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11015 " <!ENTITY en SYSTEM 'bar'>\n"
11016 "]>\n"
11017 "<doc xmlns='http://example.org/"
11018 /* 64 characters per line */
11019 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11020 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11021 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11022 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11023 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11024 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11025 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11026 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11027 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11028 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11029 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11030 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11031 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11032 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11033 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
11034 "'>\n"
11035 "&en;"
11036 "</doc>";
11037
11038 context_realloc_test(text);
11039 }
11040 END_TEST
11041
START_TEST(test_nsalloc_realloc_long_context_7)11042 START_TEST(test_nsalloc_realloc_long_context_7) {
11043 const char *text
11044 = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11045 " <!ENTITY en SYSTEM 'bar'>\n"
11046 "]>\n"
11047 "<doc xmlns='http://example.org/"
11048 /* 64 characters per line */
11049 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11050 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11051 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11052 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11053 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11054 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11055 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11056 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11057 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11058 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11059 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11060 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11061 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11062 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11063 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11064 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLM"
11065 "'>\n"
11066 "&en;"
11067 "</doc>";
11068
11069 context_realloc_test(text);
11070 }
11071 END_TEST
11072
START_TEST(test_nsalloc_realloc_long_ge_name)11073 START_TEST(test_nsalloc_realloc_long_ge_name) {
11074 const char *text
11075 = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11076 " <!ENTITY "
11077 /* 64 characters per line */
11078 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11079 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11080 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11081 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11082 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11083 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11084 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11085 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11086 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11087 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11088 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11089 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11090 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11091 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11092 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11093 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11094 " SYSTEM 'bar'>\n"
11095 "]>\n"
11096 "<doc xmlns='http://example.org/baz'>\n"
11097 "&"
11098 /* 64 characters per line */
11099 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11100 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11101 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11102 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11103 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11104 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11105 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11106 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11107 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11108 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11109 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11110 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11111 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11112 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11113 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11114 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11115 ";"
11116 "</doc>";
11117 ExtOption options[] = {
11118 {XCS("foo"), "<!ELEMENT el EMPTY>"}, {XCS("bar"), "<el/>"}, {NULL, NULL}};
11119 int i;
11120 const int max_realloc_count = 10;
11121
11122 for (i = 0; i < max_realloc_count; i++) {
11123 reallocation_count = i;
11124 XML_SetUserData(g_parser, options);
11125 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11126 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11127 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
11128 != XML_STATUS_ERROR)
11129 break;
11130 /* See comment in test_nsalloc_xmlns() */
11131 nsalloc_teardown();
11132 nsalloc_setup();
11133 }
11134 if (i == 0)
11135 fail("Parsing worked despite failing reallocations");
11136 else if (i == max_realloc_count)
11137 fail("Parsing failed even at max reallocation count");
11138 }
11139 END_TEST
11140
11141 /* Test that when a namespace is passed through the context mechanism
11142 * to an external entity parser, the parsers handle reallocation
11143 * failures correctly. The prefix is exactly the right length to
11144 * provoke particular uncommon code paths.
11145 */
START_TEST(test_nsalloc_realloc_long_context_in_dtd)11146 START_TEST(test_nsalloc_realloc_long_context_in_dtd) {
11147 const char *text1
11148 = "<!DOCTYPE "
11149 /* 64 characters per line */
11150 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11151 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11152 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11153 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11154 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11155 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11156 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11157 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11158 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11159 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11160 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11161 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11162 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11163 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11164 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11165 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11166 ":doc [\n"
11167 " <!ENTITY First SYSTEM 'foo/First'>\n"
11168 "]>\n"
11169 "<"
11170 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11171 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11172 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11173 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11174 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11175 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11176 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11177 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11178 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11179 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11180 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11181 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11182 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11183 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11184 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11185 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11186 ":doc xmlns:"
11187 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11188 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11189 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11190 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11191 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11192 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11193 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11194 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11195 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11196 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11197 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11198 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11199 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11200 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11201 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11202 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11203 "='foo/Second'>&First;";
11204 const char *text2
11205 = "</"
11206 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11207 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11208 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11209 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11210 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11211 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11212 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11213 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11214 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11215 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11216 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11217 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11218 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11219 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11220 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11221 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11222 ":doc>";
11223 ExtOption options[] = {{XCS("foo/First"), "Hello world"}, {NULL, NULL}};
11224 int i;
11225 const int max_realloc_count = 20;
11226
11227 for (i = 0; i < max_realloc_count; i++) {
11228 reallocation_count = i;
11229 XML_SetUserData(g_parser, options);
11230 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11231 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11232 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
11233 != XML_STATUS_ERROR
11234 && _XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2),
11235 XML_TRUE)
11236 != XML_STATUS_ERROR)
11237 break;
11238 /* See comment in test_nsalloc_xmlns() */
11239 nsalloc_teardown();
11240 nsalloc_setup();
11241 }
11242 if (i == 0)
11243 fail("Parsing worked despite failing reallocations");
11244 else if (i == max_realloc_count)
11245 fail("Parsing failed even at max reallocation count");
11246 }
11247 END_TEST
11248
START_TEST(test_nsalloc_long_default_in_ext)11249 START_TEST(test_nsalloc_long_default_in_ext) {
11250 const char *text
11251 = "<!DOCTYPE doc [\n"
11252 " <!ATTLIST e a1 CDATA '"
11253 /* 64 characters per line */
11254 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11255 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11256 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11257 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11258 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11259 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11260 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11261 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11262 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11263 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11264 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11265 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11266 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11267 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11268 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11269 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11270 "'>\n"
11271 " <!ENTITY x SYSTEM 'foo'>\n"
11272 "]>\n"
11273 "<doc>&x;</doc>";
11274 ExtOption options[] = {{XCS("foo"), "<e/>"}, {NULL, NULL}};
11275 int i;
11276 const int max_alloc_count = 50;
11277
11278 for (i = 0; i < max_alloc_count; i++) {
11279 allocation_count = i;
11280 XML_SetUserData(g_parser, options);
11281 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11282 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11283 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
11284 != XML_STATUS_ERROR)
11285 break;
11286
11287 /* See comment in test_nsalloc_xmlns() */
11288 nsalloc_teardown();
11289 nsalloc_setup();
11290 }
11291 if (i == 0)
11292 fail("Parsing worked despite failing allocations");
11293 else if (i == max_alloc_count)
11294 fail("Parsing failed even at max allocation count");
11295 }
11296 END_TEST
11297
START_TEST(test_nsalloc_long_systemid_in_ext)11298 START_TEST(test_nsalloc_long_systemid_in_ext) {
11299 const char *text
11300 = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11301 " <!ENTITY en SYSTEM '"
11302 /* 64 characters per line */
11303 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11304 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11305 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11306 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11307 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11308 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11309 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11310 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11311 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11312 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11313 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11314 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11315 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11316 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11317 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11318 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11319 "'>\n"
11320 "]>\n"
11321 "<doc>&en;</doc>";
11322 ExtOption options[] = {
11323 {XCS("foo"), "<!ELEMENT e EMPTY>"},
11324 {/* clang-format off */
11325 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11326 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11327 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11328 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11329 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11330 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11331 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11332 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11333 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11334 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11335 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11336 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11337 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11338 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11339 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11340 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"),
11341 /* clang-format on */
11342 "<e/>"},
11343 {NULL, NULL}};
11344 int i;
11345 const int max_alloc_count = 55;
11346
11347 for (i = 0; i < max_alloc_count; i++) {
11348 allocation_count = i;
11349 XML_SetUserData(g_parser, options);
11350 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11351 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11352 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
11353 != XML_STATUS_ERROR)
11354 break;
11355
11356 /* See comment in test_nsalloc_xmlns() */
11357 nsalloc_teardown();
11358 nsalloc_setup();
11359 }
11360 if (i == 0)
11361 fail("Parsing worked despite failing allocations");
11362 else if (i == max_alloc_count)
11363 fail("Parsing failed even at max allocation count");
11364 }
11365 END_TEST
11366
11367 /* Test the effects of allocation failure on parsing an element in a
11368 * namespace. Based on test_nsalloc_long_context.
11369 */
START_TEST(test_nsalloc_prefixed_element)11370 START_TEST(test_nsalloc_prefixed_element) {
11371 const char *text = "<!DOCTYPE pfx:element SYSTEM 'foo' [\n"
11372 " <!ATTLIST pfx:element baz ID #REQUIRED>\n"
11373 " <!ENTITY en SYSTEM 'bar'>\n"
11374 "]>\n"
11375 "<pfx:element xmlns:pfx='http://example.org/' baz='2'>\n"
11376 "&en;"
11377 "</pfx:element>";
11378 ExtOption options[] = {
11379 {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}};
11380 int i;
11381 const int max_alloc_count = 70;
11382
11383 for (i = 0; i < max_alloc_count; i++) {
11384 allocation_count = i;
11385 XML_SetUserData(g_parser, options);
11386 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11387 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11388 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
11389 != XML_STATUS_ERROR)
11390 break;
11391
11392 /* See comment in test_nsalloc_xmlns() */
11393 nsalloc_teardown();
11394 nsalloc_setup();
11395 }
11396 if (i == 0)
11397 fail("Success despite failing allocator");
11398 else if (i == max_alloc_count)
11399 fail("Failed even at full allocation count");
11400 }
11401 END_TEST
11402
11403 #if defined(XML_DTD)
11404 typedef enum XML_Status (*XmlParseFunction)(XML_Parser, const char *, int, int);
11405
11406 struct AccountingTestCase {
11407 const char *primaryText;
11408 const char *firstExternalText; /* often NULL */
11409 const char *secondExternalText; /* often NULL */
11410 const unsigned long long expectedCountBytesIndirectExtra;
11411 XML_Bool singleBytesWanted;
11412 };
11413
11414 static int
accounting_external_entity_ref_handler(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)11415 accounting_external_entity_ref_handler(XML_Parser parser,
11416 const XML_Char *context,
11417 const XML_Char *base,
11418 const XML_Char *systemId,
11419 const XML_Char *publicId) {
11420 UNUSED_P(context);
11421 UNUSED_P(base);
11422 UNUSED_P(publicId);
11423
11424 const struct AccountingTestCase *const testCase
11425 = (const struct AccountingTestCase *)XML_GetUserData(parser);
11426
11427 const char *externalText = NULL;
11428 if (xcstrcmp(systemId, XCS("first.ent")) == 0) {
11429 externalText = testCase->firstExternalText;
11430 } else if (xcstrcmp(systemId, XCS("second.ent")) == 0) {
11431 externalText = testCase->secondExternalText;
11432 } else {
11433 assert(! "systemId is neither \"first.ent\" nor \"second.ent\"");
11434 }
11435 assert(externalText);
11436
11437 XML_Parser entParser = XML_ExternalEntityParserCreate(parser, context, 0);
11438 assert(entParser);
11439
11440 const XmlParseFunction xmlParseFunction
11441 = testCase->singleBytesWanted ? _XML_Parse_SINGLE_BYTES : XML_Parse;
11442
11443 const enum XML_Status status = xmlParseFunction(
11444 entParser, externalText, (int)strlen(externalText), XML_TRUE);
11445
11446 XML_ParserFree(entParser);
11447 return status;
11448 }
11449
START_TEST(test_accounting_precision)11450 START_TEST(test_accounting_precision) {
11451 const XML_Bool filled_later = XML_TRUE; /* value is arbitrary */
11452 struct AccountingTestCase cases[] = {
11453 {"<e/>", NULL, NULL, 0, 0},
11454 {"<e></e>", NULL, NULL, 0, 0},
11455
11456 /* Attributes */
11457 {"<e k1=\"v2\" k2=\"v2\"/>", NULL, NULL, 0, filled_later},
11458 {"<e k1=\"v2\" k2=\"v2\"></e>", NULL, NULL, 0, 0},
11459 {"<p:e xmlns:p=\"https://domain.invalid/\" />", NULL, NULL, 0,
11460 filled_later},
11461 {"<e k=\"&'><"\" />", NULL, NULL,
11462 sizeof(XML_Char) * 5 /* number of predefined entites */, filled_later},
11463 {"<e1 xmlns='https://example.org/'>\n"
11464 " <e2 xmlns=''/>\n"
11465 "</e1>",
11466 NULL, NULL, 0, filled_later},
11467
11468 /* Text */
11469 {"<e>text</e>", NULL, NULL, 0, filled_later},
11470 {"<e1><e2>text1<e3/>text2</e2></e1>", NULL, NULL, 0, filled_later},
11471 {"<e>&'><"</e>", NULL, NULL,
11472 sizeof(XML_Char) * 5 /* number of predefined entites */, filled_later},
11473 {"<e>A)</e>", NULL, NULL, 0, filled_later},
11474
11475 /* Prolog */
11476 {"<?xml version=\"1.0\"?><root/>", NULL, NULL, 0, filled_later},
11477
11478 /* Whitespace */
11479 {" <e1> <e2> </e2> </e1> ", NULL, NULL, 0, filled_later},
11480 {"<e1 ><e2 /></e1 >", NULL, NULL, 0, filled_later},
11481 {"<e1><e2 k = \"v\"/><e3 k = 'v'/></e1>", NULL, NULL, 0, filled_later},
11482
11483 /* Comments */
11484 {"<!-- Comment --><e><!-- Comment --></e>", NULL, NULL, 0, filled_later},
11485
11486 /* Processing instructions */
11487 {"<?xml-stylesheet type=\"text/xsl\" href=\"https://domain.invalid/\" media=\"all\"?><e/>",
11488 NULL, NULL, 0, filled_later},
11489 {"<?pi0?><?pi1 ?><?pi2 ?><!DOCTYPE r SYSTEM 'first.ent'><r/>",
11490 "<?pi3?><!ENTITY % e1 SYSTEM 'second.ent'><?pi4?>%e1;<?pi5?>", "<?pi6?>",
11491 0, filled_later},
11492
11493 /* CDATA */
11494 {"<e><![CDATA[one two three]]></e>", NULL, NULL, 0, filled_later},
11495 /* The following is the essence of this OSS-Fuzz finding:
11496 https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=34302
11497 https://oss-fuzz.com/testcase-detail/4860575394955264
11498 */
11499 {"<!DOCTYPE r [\n"
11500 "<!ENTITY e \"111<![CDATA[2 <= 2]]>333\">\n"
11501 "]>\n"
11502 "<r>&e;</r>\n",
11503 NULL, NULL, sizeof(XML_Char) * strlen("111<![CDATA[2 <= 2]]>333"),
11504 filled_later},
11505
11506 /* Conditional sections */
11507 {"<!DOCTYPE r [\n"
11508 "<!ENTITY % draft 'INCLUDE'>\n"
11509 "<!ENTITY % final 'IGNORE'>\n"
11510 "<!ENTITY % import SYSTEM \"first.ent\">\n"
11511 "%import;\n"
11512 "]>\n"
11513 "<r/>\n",
11514 "<![%draft;[<!--1-->]]>\n"
11515 "<![%final;[<!--22-->]]>",
11516 NULL, sizeof(XML_Char) * (strlen("INCLUDE") + strlen("IGNORE")),
11517 filled_later},
11518
11519 /* General entities */
11520 {"<!DOCTYPE root [\n"
11521 "<!ENTITY nine \"123456789\">\n"
11522 "]>\n"
11523 "<root>&nine;</root>",
11524 NULL, NULL, sizeof(XML_Char) * strlen("123456789"), filled_later},
11525 {"<!DOCTYPE root [\n"
11526 "<!ENTITY nine \"123456789\">\n"
11527 "]>\n"
11528 "<root k1=\"&nine;\"/>",
11529 NULL, NULL, sizeof(XML_Char) * strlen("123456789"), filled_later},
11530 {"<!DOCTYPE root [\n"
11531 "<!ENTITY nine \"123456789\">\n"
11532 "<!ENTITY nine2 \"&nine;&nine;\">\n"
11533 "]>\n"
11534 "<root>&nine2;&nine2;&nine2;</root>",
11535 NULL, NULL,
11536 sizeof(XML_Char) * 3 /* calls to &nine2; */ * 2 /* calls to &nine; */
11537 * (strlen("&nine;") + strlen("123456789")),
11538 filled_later},
11539 {"<!DOCTYPE r [\n"
11540 " <!ENTITY five SYSTEM 'first.ent'>\n"
11541 "]>\n"
11542 "<r>&five;</r>",
11543 "12345", NULL, 0, filled_later},
11544
11545 /* Parameter entities */
11546 {"<!DOCTYPE r [\n"
11547 "<!ENTITY % comment \"<!---->\">\n"
11548 "%comment;\n"
11549 "]>\n"
11550 "<r/>",
11551 NULL, NULL, sizeof(XML_Char) * strlen("<!---->"), filled_later},
11552 {"<!DOCTYPE r [\n"
11553 "<!ENTITY % ninedef \"<!ENTITY nine "123456789">\">\n"
11554 "%ninedef;\n"
11555 "]>\n"
11556 "<r>&nine;</r>",
11557 NULL, NULL,
11558 sizeof(XML_Char)
11559 * (strlen("<!ENTITY nine \"123456789\">") + strlen("123456789")),
11560 filled_later},
11561 {"<!DOCTYPE r [\n"
11562 "<!ENTITY % comment \"<!--1-->\">\n"
11563 "<!ENTITY % comment2 \"%comment;<!--22-->%comment;\">\n"
11564 "%comment2;\n"
11565 "]>\n"
11566 "<r/>\n",
11567 NULL, NULL,
11568 sizeof(XML_Char)
11569 * (strlen("%comment;<!--22-->%comment;") + 2 * strlen("<!--1-->")),
11570 filled_later},
11571 {"<!DOCTYPE r [\n"
11572 " <!ENTITY % five \"12345\">\n"
11573 " <!ENTITY % five2def \"<!ENTITY five2 "[%five;][%five;]]]]">\">\n"
11574 " %five2def;\n"
11575 "]>\n"
11576 "<r>&five2;</r>",
11577 NULL, NULL, /* from "%five2def;": */
11578 sizeof(XML_Char)
11579 * (strlen("<!ENTITY five2 \"[%five;][%five;]]]]\">")
11580 + 2 /* calls to "%five;" */ * strlen("12345")
11581 + /* from "&five2;": */ strlen("[12345][12345]]]]")),
11582 filled_later},
11583 {"<!DOCTYPE r SYSTEM \"first.ent\">\n"
11584 "<r/>",
11585 "<!ENTITY % comment '<!--1-->'>\n"
11586 "<!ENTITY % comment2 '<!--22-->%comment;<!--22-->%comment;<!--22-->'>\n"
11587 "%comment2;",
11588 NULL,
11589 sizeof(XML_Char)
11590 * (strlen("<!--22-->%comment;<!--22-->%comment;<!--22-->")
11591 + 2 /* calls to "%comment;" */ * strlen("<!---->")),
11592 filled_later},
11593 {"<!DOCTYPE r SYSTEM 'first.ent'>\n"
11594 "<r/>",
11595 "<!ENTITY % e1 PUBLIC 'foo' 'second.ent'>\n"
11596 "<!ENTITY % e2 '<!--22-->%e1;<!--22-->'>\n"
11597 "%e2;\n",
11598 "<!--1-->", sizeof(XML_Char) * strlen("<!--22--><!--1--><!--22-->"),
11599 filled_later},
11600 {
11601 "<!DOCTYPE r SYSTEM 'first.ent'>\n"
11602 "<r/>",
11603 "<!ENTITY % e1 SYSTEM 'second.ent'>\n"
11604 "<!ENTITY % e2 '%e1;'>",
11605 "<?xml version='1.0' encoding='utf-8'?>\n"
11606 "hello\n"
11607 "xml" /* without trailing newline! */,
11608 0,
11609 filled_later,
11610 },
11611 {
11612 "<!DOCTYPE r SYSTEM 'first.ent'>\n"
11613 "<r/>",
11614 "<!ENTITY % e1 SYSTEM 'second.ent'>\n"
11615 "<!ENTITY % e2 '%e1;'>",
11616 "<?xml version='1.0' encoding='utf-8'?>\n"
11617 "hello\n"
11618 "xml\n" /* with trailing newline! */,
11619 0,
11620 filled_later,
11621 },
11622 {"<!DOCTYPE doc SYSTEM 'first.ent'>\n"
11623 "<doc></doc>\n",
11624 "<!ELEMENT doc EMPTY>\n"
11625 "<!ENTITY % e1 SYSTEM 'second.ent'>\n"
11626 "<!ENTITY % e2 '%e1;'>\n"
11627 "%e1;\n",
11628 "\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>" /* UTF-8 BOM */,
11629 strlen("\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>"), filled_later},
11630 {"<!DOCTYPE r [\n"
11631 " <!ENTITY five SYSTEM 'first.ent'>\n"
11632 "]>\n"
11633 "<r>&five;</r>",
11634 "\xEF\xBB\xBF" /* UTF-8 BOM */, NULL, 0, filled_later},
11635 };
11636
11637 const size_t countCases = sizeof(cases) / sizeof(cases[0]);
11638 size_t u = 0;
11639 for (; u < countCases; u++) {
11640 size_t v = 0;
11641 for (; v < 2; v++) {
11642 const XML_Bool singleBytesWanted = (v == 0) ? XML_FALSE : XML_TRUE;
11643 const unsigned long long expectedCountBytesDirect
11644 = strlen(cases[u].primaryText);
11645 const unsigned long long expectedCountBytesIndirect
11646 = (cases[u].firstExternalText ? strlen(cases[u].firstExternalText)
11647 : 0)
11648 + (cases[u].secondExternalText ? strlen(cases[u].secondExternalText)
11649 : 0)
11650 + cases[u].expectedCountBytesIndirectExtra;
11651
11652 XML_Parser parser = XML_ParserCreate(NULL);
11653 XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11654 if (cases[u].firstExternalText) {
11655 XML_SetExternalEntityRefHandler(parser,
11656 accounting_external_entity_ref_handler);
11657 XML_SetUserData(parser, (void *)&cases[u]);
11658 cases[u].singleBytesWanted = singleBytesWanted;
11659 }
11660
11661 const XmlParseFunction xmlParseFunction
11662 = singleBytesWanted ? _XML_Parse_SINGLE_BYTES : XML_Parse;
11663
11664 enum XML_Status status
11665 = xmlParseFunction(parser, cases[u].primaryText,
11666 (int)strlen(cases[u].primaryText), XML_TRUE);
11667 if (status != XML_STATUS_OK) {
11668 _xml_failure(parser, __FILE__, __LINE__);
11669 }
11670
11671 const unsigned long long actualCountBytesDirect
11672 = testingAccountingGetCountBytesDirect(parser);
11673 const unsigned long long actualCountBytesIndirect
11674 = testingAccountingGetCountBytesIndirect(parser);
11675
11676 XML_ParserFree(parser);
11677
11678 if (actualCountBytesDirect != expectedCountBytesDirect) {
11679 fprintf(
11680 stderr,
11681 "Document " EXPAT_FMT_SIZE_T("") " of " EXPAT_FMT_SIZE_T("") ", %s: Expected " EXPAT_FMT_ULL(
11682 "") " count direct bytes, got " EXPAT_FMT_ULL("") " instead.\n",
11683 u + 1, countCases, singleBytesWanted ? "single bytes" : "chunks",
11684 expectedCountBytesDirect, actualCountBytesDirect);
11685 fail("Count of direct bytes is off");
11686 }
11687
11688 if (actualCountBytesIndirect != expectedCountBytesIndirect) {
11689 fprintf(
11690 stderr,
11691 "Document " EXPAT_FMT_SIZE_T("") " of " EXPAT_FMT_SIZE_T("") ", %s: Expected " EXPAT_FMT_ULL(
11692 "") " count indirect bytes, got " EXPAT_FMT_ULL("") " instead.\n",
11693 u + 1, countCases, singleBytesWanted ? "single bytes" : "chunks",
11694 expectedCountBytesIndirect, actualCountBytesIndirect);
11695 fail("Count of indirect bytes is off");
11696 }
11697 }
11698 }
11699 }
11700 END_TEST
11701
START_TEST(test_billion_laughs_attack_protection_api)11702 START_TEST(test_billion_laughs_attack_protection_api) {
11703 XML_Parser parserWithoutParent = XML_ParserCreate(NULL);
11704 XML_Parser parserWithParent
11705 = XML_ExternalEntityParserCreate(parserWithoutParent, NULL, NULL);
11706 if (parserWithoutParent == NULL)
11707 fail("parserWithoutParent is NULL");
11708 if (parserWithParent == NULL)
11709 fail("parserWithParent is NULL");
11710
11711 // XML_SetBillionLaughsAttackProtectionMaximumAmplification, error cases
11712 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(NULL, 123.0f)
11713 == XML_TRUE)
11714 fail("Call with NULL parser is NOT supposed to succeed");
11715 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(parserWithParent,
11716 123.0f)
11717 == XML_TRUE)
11718 fail("Call with non-root parser is NOT supposed to succeed");
11719 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
11720 parserWithoutParent, NAN)
11721 == XML_TRUE)
11722 fail("Call with NaN limit is NOT supposed to succeed");
11723 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
11724 parserWithoutParent, -1.0f)
11725 == XML_TRUE)
11726 fail("Call with negative limit is NOT supposed to succeed");
11727 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
11728 parserWithoutParent, 0.9f)
11729 == XML_TRUE)
11730 fail("Call with positive limit <1.0 is NOT supposed to succeed");
11731
11732 // XML_SetBillionLaughsAttackProtectionMaximumAmplification, success cases
11733 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
11734 parserWithoutParent, 1.0f)
11735 == XML_FALSE)
11736 fail("Call with positive limit >=1.0 is supposed to succeed");
11737 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
11738 parserWithoutParent, 123456.789f)
11739 == XML_FALSE)
11740 fail("Call with positive limit >=1.0 is supposed to succeed");
11741 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
11742 parserWithoutParent, INFINITY)
11743 == XML_FALSE)
11744 fail("Call with positive limit >=1.0 is supposed to succeed");
11745
11746 // XML_SetBillionLaughsAttackProtectionActivationThreshold, error cases
11747 if (XML_SetBillionLaughsAttackProtectionActivationThreshold(NULL, 123)
11748 == XML_TRUE)
11749 fail("Call with NULL parser is NOT supposed to succeed");
11750 if (XML_SetBillionLaughsAttackProtectionActivationThreshold(parserWithParent,
11751 123)
11752 == XML_TRUE)
11753 fail("Call with non-root parser is NOT supposed to succeed");
11754
11755 // XML_SetBillionLaughsAttackProtectionActivationThreshold, success cases
11756 if (XML_SetBillionLaughsAttackProtectionActivationThreshold(
11757 parserWithoutParent, 123)
11758 == XML_FALSE)
11759 fail("Call with non-NULL parentless parser is supposed to succeed");
11760
11761 XML_ParserFree(parserWithParent);
11762 XML_ParserFree(parserWithoutParent);
11763 }
11764 END_TEST
11765
START_TEST(test_helper_unsigned_char_to_printable)11766 START_TEST(test_helper_unsigned_char_to_printable) {
11767 // Smoke test
11768 unsigned char uc = 0;
11769 for (; uc < (unsigned char)-1; uc++) {
11770 const char *const printable = unsignedCharToPrintable(uc);
11771 if (printable == NULL)
11772 fail("unsignedCharToPrintable returned NULL");
11773 if (strlen(printable) < (size_t)1)
11774 fail("unsignedCharToPrintable returned empty string");
11775 }
11776
11777 // Two concrete samples
11778 if (strcmp(unsignedCharToPrintable('A'), "A") != 0)
11779 fail("unsignedCharToPrintable result mistaken");
11780 if (strcmp(unsignedCharToPrintable('\\'), "\\\\") != 0)
11781 fail("unsignedCharToPrintable result mistaken");
11782 }
11783 END_TEST
11784
START_TEST(test_amplification_isolated_external_parser)11785 START_TEST(test_amplification_isolated_external_parser) {
11786 // NOTE: Length 44 is precisely twice the length of "<!ENTITY a SYSTEM 'b'>"
11787 // (22) that is used in function accountingGetCurrentAmplification in
11788 // xmlparse.c.
11789 // 1.........1.........1.........1.........1..4 => 44
11790 const char doc[] = "<!ENTITY % p1 '123456789_123456789_1234567'>";
11791 const int docLen = (int)sizeof(doc) - 1;
11792 const float maximumToleratedAmplification = 2.0f;
11793
11794 struct TestCase {
11795 int offsetOfThreshold;
11796 enum XML_Status expectedStatus;
11797 };
11798
11799 struct TestCase cases[] = {
11800 {-2, XML_STATUS_ERROR}, {-1, XML_STATUS_ERROR}, {0, XML_STATUS_ERROR},
11801 {+1, XML_STATUS_OK}, {+2, XML_STATUS_OK},
11802 };
11803
11804 for (size_t i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) {
11805 const int offsetOfThreshold = cases[i].offsetOfThreshold;
11806 const enum XML_Status expectedStatus = cases[i].expectedStatus;
11807 const unsigned long long activationThresholdBytes
11808 = docLen + offsetOfThreshold;
11809
11810 set_subtest("offsetOfThreshold=%d, expectedStatus=%d", offsetOfThreshold,
11811 expectedStatus);
11812
11813 XML_Parser parser = XML_ParserCreate(NULL);
11814 assert_true(parser != NULL);
11815
11816 assert_true(XML_SetBillionLaughsAttackProtectionMaximumAmplification(
11817 parser, maximumToleratedAmplification)
11818 == XML_TRUE);
11819 assert_true(XML_SetBillionLaughsAttackProtectionActivationThreshold(
11820 parser, activationThresholdBytes)
11821 == XML_TRUE);
11822
11823 XML_Parser ext_parser = XML_ExternalEntityParserCreate(parser, NULL, NULL);
11824 assert_true(ext_parser != NULL);
11825
11826 const enum XML_Status actualStatus
11827 = _XML_Parse_SINGLE_BYTES(ext_parser, doc, docLen, XML_TRUE);
11828
11829 assert_true(actualStatus == expectedStatus);
11830 if (actualStatus != XML_STATUS_OK) {
11831 assert_true(XML_GetErrorCode(ext_parser)
11832 == XML_ERROR_AMPLIFICATION_LIMIT_BREACH);
11833 }
11834
11835 XML_ParserFree(ext_parser);
11836 XML_ParserFree(parser);
11837 }
11838 }
11839 END_TEST
11840
11841 #endif // defined(XML_DTD)
11842
11843 static Suite *
make_suite(void)11844 make_suite(void) {
11845 Suite *s = suite_create("basic");
11846 TCase *tc_basic = tcase_create("basic tests");
11847 TCase *tc_namespace = tcase_create("XML namespaces");
11848 TCase *tc_misc = tcase_create("miscellaneous tests");
11849 TCase *tc_alloc = tcase_create("allocation tests");
11850 TCase *tc_nsalloc = tcase_create("namespace allocation tests");
11851 #if defined(XML_DTD)
11852 TCase *tc_accounting = tcase_create("accounting tests");
11853 #endif
11854
11855 suite_add_tcase(s, tc_basic);
11856 tcase_add_checked_fixture(tc_basic, basic_setup, basic_teardown);
11857 tcase_add_test(tc_basic, test_nul_byte);
11858 tcase_add_test(tc_basic, test_u0000_char);
11859 tcase_add_test(tc_basic, test_siphash_self);
11860 tcase_add_test(tc_basic, test_siphash_spec);
11861 tcase_add_test(tc_basic, test_bom_utf8);
11862 tcase_add_test(tc_basic, test_bom_utf16_be);
11863 tcase_add_test(tc_basic, test_bom_utf16_le);
11864 tcase_add_test(tc_basic, test_nobom_utf16_le);
11865 tcase_add_test(tc_basic, test_illegal_utf8);
11866 tcase_add_test(tc_basic, test_utf8_auto_align);
11867 tcase_add_test(tc_basic, test_utf16);
11868 tcase_add_test(tc_basic, test_utf16_le_epilog_newline);
11869 tcase_add_test(tc_basic, test_not_utf16);
11870 tcase_add_test(tc_basic, test_bad_encoding);
11871 tcase_add_test(tc_basic, test_latin1_umlauts);
11872 tcase_add_test(tc_basic, test_long_utf8_character);
11873 tcase_add_test(tc_basic, test_long_latin1_attribute);
11874 tcase_add_test(tc_basic, test_long_ascii_attribute);
11875 /* Regression test for SF bug #491986. */
11876 tcase_add_test(tc_basic, test_danish_latin1);
11877 /* Regression test for SF bug #514281. */
11878 tcase_add_test(tc_basic, test_french_charref_hexidecimal);
11879 tcase_add_test(tc_basic, test_french_charref_decimal);
11880 tcase_add_test(tc_basic, test_french_latin1);
11881 tcase_add_test(tc_basic, test_french_utf8);
11882 tcase_add_test(tc_basic, test_utf8_false_rejection);
11883 tcase_add_test(tc_basic, test_line_number_after_parse);
11884 tcase_add_test(tc_basic, test_column_number_after_parse);
11885 tcase_add_test(tc_basic, test_line_and_column_numbers_inside_handlers);
11886 tcase_add_test(tc_basic, test_line_number_after_error);
11887 tcase_add_test(tc_basic, test_column_number_after_error);
11888 tcase_add_test(tc_basic, test_really_long_lines);
11889 tcase_add_test(tc_basic, test_really_long_encoded_lines);
11890 tcase_add_test(tc_basic, test_end_element_events);
11891 tcase_add_test(tc_basic, test_attr_whitespace_normalization);
11892 tcase_add_test(tc_basic, test_xmldecl_misplaced);
11893 tcase_add_test(tc_basic, test_xmldecl_invalid);
11894 tcase_add_test(tc_basic, test_xmldecl_missing_attr);
11895 tcase_add_test(tc_basic, test_xmldecl_missing_value);
11896 tcase_add_test(tc_basic, test_unknown_encoding_internal_entity);
11897 tcase_add_test(tc_basic, test_unrecognised_encoding_internal_entity);
11898 tcase_add_test(tc_basic, test_wfc_undeclared_entity_unread_external_subset);
11899 tcase_add_test(tc_basic, test_wfc_undeclared_entity_no_external_subset);
11900 tcase_add_test(tc_basic, test_wfc_undeclared_entity_standalone);
11901 tcase_add_test(tc_basic, test_wfc_undeclared_entity_with_external_subset);
11902 tcase_add_test(tc_basic, test_not_standalone_handler_reject);
11903 tcase_add_test(tc_basic, test_not_standalone_handler_accept);
11904 tcase_add_test(tc_basic,
11905 test_wfc_undeclared_entity_with_external_subset_standalone);
11906 tcase_add_test(tc_basic, test_entity_with_external_subset_unless_standalone);
11907 tcase_add_test(tc_basic, test_wfc_no_recursive_entity_refs);
11908 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_set_encoding);
11909 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_no_handler);
11910 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_set_bom);
11911 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_bad_encoding);
11912 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_bad_encoding_2);
11913 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_invalid_parse);
11914 tcase_add_test__ifdef_xml_dtd(tc_basic,
11915 test_ext_entity_invalid_suspended_parse);
11916 tcase_add_test(tc_basic, test_dtd_default_handling);
11917 tcase_add_test(tc_basic, test_dtd_attr_handling);
11918 tcase_add_test(tc_basic, test_empty_ns_without_namespaces);
11919 tcase_add_test(tc_basic, test_ns_in_attribute_default_without_namespaces);
11920 tcase_add_test(tc_basic, test_stop_parser_between_char_data_calls);
11921 tcase_add_test(tc_basic, test_suspend_parser_between_char_data_calls);
11922 tcase_add_test(tc_basic, test_repeated_stop_parser_between_char_data_calls);
11923 tcase_add_test(tc_basic, test_good_cdata_ascii);
11924 tcase_add_test(tc_basic, test_good_cdata_utf16);
11925 tcase_add_test(tc_basic, test_good_cdata_utf16_le);
11926 tcase_add_test(tc_basic, test_long_cdata_utf16);
11927 tcase_add_test(tc_basic, test_multichar_cdata_utf16);
11928 tcase_add_test(tc_basic, test_utf16_bad_surrogate_pair);
11929 tcase_add_test(tc_basic, test_bad_cdata);
11930 tcase_add_test(tc_basic, test_bad_cdata_utf16);
11931 tcase_add_test(tc_basic, test_stop_parser_between_cdata_calls);
11932 tcase_add_test(tc_basic, test_suspend_parser_between_cdata_calls);
11933 tcase_add_test(tc_basic, test_memory_allocation);
11934 tcase_add_test(tc_basic, test_default_current);
11935 tcase_add_test(tc_basic, test_dtd_elements);
11936 tcase_add_test__ifdef_xml_dtd(tc_basic, test_set_foreign_dtd);
11937 tcase_add_test__ifdef_xml_dtd(tc_basic, test_foreign_dtd_not_standalone);
11938 tcase_add_test__ifdef_xml_dtd(tc_basic, test_invalid_foreign_dtd);
11939 tcase_add_test__ifdef_xml_dtd(tc_basic, test_foreign_dtd_with_doctype);
11940 tcase_add_test__ifdef_xml_dtd(tc_basic,
11941 test_foreign_dtd_without_external_subset);
11942 tcase_add_test__ifdef_xml_dtd(tc_basic, test_empty_foreign_dtd);
11943 tcase_add_test(tc_basic, test_set_base);
11944 tcase_add_test(tc_basic, test_attributes);
11945 tcase_add_test(tc_basic, test_reset_in_entity);
11946 tcase_add_test(tc_basic, test_resume_invalid_parse);
11947 tcase_add_test(tc_basic, test_resume_resuspended);
11948 tcase_add_test(tc_basic, test_cdata_default);
11949 tcase_add_test(tc_basic, test_subordinate_reset);
11950 tcase_add_test(tc_basic, test_subordinate_suspend);
11951 tcase_add_test(tc_basic, test_subordinate_xdecl_suspend);
11952 tcase_add_test(tc_basic, test_subordinate_xdecl_abort);
11953 tcase_add_test(tc_basic, test_explicit_encoding);
11954 tcase_add_test(tc_basic, test_trailing_cr);
11955 tcase_add_test(tc_basic, test_ext_entity_trailing_cr);
11956 tcase_add_test(tc_basic, test_trailing_rsqb);
11957 tcase_add_test(tc_basic, test_ext_entity_trailing_rsqb);
11958 tcase_add_test(tc_basic, test_ext_entity_good_cdata);
11959 tcase_add_test__ifdef_xml_dtd(tc_basic, test_user_parameters);
11960 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_ref_parameter);
11961 tcase_add_test(tc_basic, test_empty_parse);
11962 tcase_add_test(tc_basic, test_negative_len_parse);
11963 tcase_add_test(tc_basic, test_negative_len_parse_buffer);
11964 tcase_add_test(tc_basic, test_get_buffer_1);
11965 tcase_add_test(tc_basic, test_get_buffer_2);
11966 tcase_add_test(tc_basic, test_byte_info_at_end);
11967 tcase_add_test(tc_basic, test_byte_info_at_error);
11968 tcase_add_test(tc_basic, test_byte_info_at_cdata);
11969 tcase_add_test(tc_basic, test_predefined_entities);
11970 tcase_add_test__ifdef_xml_dtd(tc_basic, test_invalid_tag_in_dtd);
11971 tcase_add_test(tc_basic, test_not_predefined_entities);
11972 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section);
11973 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section_utf16);
11974 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section_utf16_be);
11975 tcase_add_test__ifdef_xml_dtd(tc_basic, test_bad_ignore_section);
11976 tcase_add_test__ifdef_xml_dtd(tc_basic, test_external_entity_values);
11977 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_not_standalone);
11978 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_value_abort);
11979 tcase_add_test(tc_basic, test_bad_public_doctype);
11980 tcase_add_test(tc_basic, test_attribute_enum_value);
11981 tcase_add_test(tc_basic, test_predefined_entity_redefinition);
11982 tcase_add_test__ifdef_xml_dtd(tc_basic, test_dtd_stop_processing);
11983 tcase_add_test(tc_basic, test_public_notation_no_sysid);
11984 tcase_add_test(tc_basic, test_nested_groups);
11985 tcase_add_test(tc_basic, test_group_choice);
11986 tcase_add_test(tc_basic, test_standalone_parameter_entity);
11987 tcase_add_test__ifdef_xml_dtd(tc_basic, test_skipped_parameter_entity);
11988 tcase_add_test__ifdef_xml_dtd(tc_basic,
11989 test_recursive_external_parameter_entity);
11990 tcase_add_test(tc_basic, test_undefined_ext_entity_in_external_dtd);
11991 tcase_add_test(tc_basic, test_suspend_xdecl);
11992 tcase_add_test(tc_basic, test_abort_epilog);
11993 tcase_add_test(tc_basic, test_abort_epilog_2);
11994 tcase_add_test(tc_basic, test_suspend_epilog);
11995 tcase_add_test(tc_basic, test_suspend_in_sole_empty_tag);
11996 tcase_add_test(tc_basic, test_unfinished_epilog);
11997 tcase_add_test(tc_basic, test_partial_char_in_epilog);
11998 tcase_add_test(tc_basic, test_hash_collision);
11999 tcase_add_test__ifdef_xml_dtd(tc_basic, test_suspend_resume_internal_entity);
12000 tcase_add_test__ifdef_xml_dtd(tc_basic,
12001 test_suspend_resume_internal_entity_issue_629);
12002 tcase_add_test__ifdef_xml_dtd(tc_basic, test_resume_entity_with_syntax_error);
12003 tcase_add_test__ifdef_xml_dtd(tc_basic, test_suspend_resume_parameter_entity);
12004 tcase_add_test(tc_basic, test_restart_on_error);
12005 tcase_add_test(tc_basic, test_reject_lt_in_attribute_value);
12006 tcase_add_test(tc_basic, test_reject_unfinished_param_in_att_value);
12007 tcase_add_test(tc_basic, test_trailing_cr_in_att_value);
12008 tcase_add_test(tc_basic, test_standalone_internal_entity);
12009 tcase_add_test(tc_basic, test_skipped_external_entity);
12010 tcase_add_test(tc_basic, test_skipped_null_loaded_ext_entity);
12011 tcase_add_test(tc_basic, test_skipped_unloaded_ext_entity);
12012 tcase_add_test__ifdef_xml_dtd(tc_basic, test_param_entity_with_trailing_cr);
12013 tcase_add_test(tc_basic, test_invalid_character_entity);
12014 tcase_add_test(tc_basic, test_invalid_character_entity_2);
12015 tcase_add_test(tc_basic, test_invalid_character_entity_3);
12016 tcase_add_test(tc_basic, test_invalid_character_entity_4);
12017 tcase_add_test(tc_basic, test_pi_handled_in_default);
12018 tcase_add_test(tc_basic, test_comment_handled_in_default);
12019 tcase_add_test(tc_basic, test_pi_yml);
12020 tcase_add_test(tc_basic, test_pi_xnl);
12021 tcase_add_test(tc_basic, test_pi_xmm);
12022 tcase_add_test(tc_basic, test_utf16_pi);
12023 tcase_add_test(tc_basic, test_utf16_be_pi);
12024 tcase_add_test(tc_basic, test_utf16_be_comment);
12025 tcase_add_test(tc_basic, test_utf16_le_comment);
12026 tcase_add_test(tc_basic, test_missing_encoding_conversion_fn);
12027 tcase_add_test(tc_basic, test_failing_encoding_conversion_fn);
12028 tcase_add_test(tc_basic, test_unknown_encoding_success);
12029 tcase_add_test(tc_basic, test_unknown_encoding_bad_name);
12030 tcase_add_test(tc_basic, test_unknown_encoding_bad_name_2);
12031 tcase_add_test(tc_basic, test_unknown_encoding_long_name_1);
12032 tcase_add_test(tc_basic, test_unknown_encoding_long_name_2);
12033 tcase_add_test(tc_basic, test_invalid_unknown_encoding);
12034 tcase_add_test(tc_basic, test_unknown_ascii_encoding_ok);
12035 tcase_add_test(tc_basic, test_unknown_ascii_encoding_fail);
12036 tcase_add_test(tc_basic, test_unknown_encoding_invalid_length);
12037 tcase_add_test(tc_basic, test_unknown_encoding_invalid_topbit);
12038 tcase_add_test(tc_basic, test_unknown_encoding_invalid_surrogate);
12039 tcase_add_test(tc_basic, test_unknown_encoding_invalid_high);
12040 tcase_add_test(tc_basic, test_unknown_encoding_invalid_attr_value);
12041 tcase_add_test(tc_basic, test_ext_entity_latin1_utf16le_bom);
12042 tcase_add_test(tc_basic, test_ext_entity_latin1_utf16be_bom);
12043 tcase_add_test(tc_basic, test_ext_entity_latin1_utf16le_bom2);
12044 tcase_add_test(tc_basic, test_ext_entity_latin1_utf16be_bom2);
12045 tcase_add_test(tc_basic, test_ext_entity_utf16_be);
12046 tcase_add_test(tc_basic, test_ext_entity_utf16_le);
12047 tcase_add_test(tc_basic, test_ext_entity_utf16_unknown);
12048 tcase_add_test(tc_basic, test_ext_entity_utf8_non_bom);
12049 tcase_add_test(tc_basic, test_utf8_in_cdata_section);
12050 tcase_add_test(tc_basic, test_utf8_in_cdata_section_2);
12051 tcase_add_test(tc_basic, test_trailing_spaces_in_elements);
12052 tcase_add_test(tc_basic, test_utf16_attribute);
12053 tcase_add_test(tc_basic, test_utf16_second_attr);
12054 tcase_add_test(tc_basic, test_attr_after_solidus);
12055 tcase_add_test__ifdef_xml_dtd(tc_basic, test_utf16_pe);
12056 tcase_add_test(tc_basic, test_bad_attr_desc_keyword);
12057 tcase_add_test(tc_basic, test_bad_attr_desc_keyword_utf16);
12058 tcase_add_test(tc_basic, test_bad_doctype);
12059 tcase_add_test(tc_basic, test_bad_doctype_utf16);
12060 tcase_add_test(tc_basic, test_bad_doctype_plus);
12061 tcase_add_test(tc_basic, test_bad_doctype_star);
12062 tcase_add_test(tc_basic, test_bad_doctype_query);
12063 tcase_add_test__ifdef_xml_dtd(tc_basic, test_unknown_encoding_bad_ignore);
12064 tcase_add_test(tc_basic, test_entity_in_utf16_be_attr);
12065 tcase_add_test(tc_basic, test_entity_in_utf16_le_attr);
12066 tcase_add_test__ifdef_xml_dtd(tc_basic, test_entity_public_utf16_be);
12067 tcase_add_test__ifdef_xml_dtd(tc_basic, test_entity_public_utf16_le);
12068 tcase_add_test(tc_basic, test_short_doctype);
12069 tcase_add_test(tc_basic, test_short_doctype_2);
12070 tcase_add_test(tc_basic, test_short_doctype_3);
12071 tcase_add_test(tc_basic, test_long_doctype);
12072 tcase_add_test(tc_basic, test_bad_entity);
12073 tcase_add_test(tc_basic, test_bad_entity_2);
12074 tcase_add_test(tc_basic, test_bad_entity_3);
12075 tcase_add_test(tc_basic, test_bad_entity_4);
12076 tcase_add_test(tc_basic, test_bad_notation);
12077 tcase_add_test(tc_basic, test_default_doctype_handler);
12078 tcase_add_test(tc_basic, test_empty_element_abort);
12079
12080 suite_add_tcase(s, tc_namespace);
12081 tcase_add_checked_fixture(tc_namespace, namespace_setup, namespace_teardown);
12082 tcase_add_test(tc_namespace, test_return_ns_triplet);
12083 tcase_add_test(tc_namespace, test_ns_tagname_overwrite);
12084 tcase_add_test(tc_namespace, test_ns_tagname_overwrite_triplet);
12085 tcase_add_test(tc_namespace, test_start_ns_clears_start_element);
12086 tcase_add_test__ifdef_xml_dtd(tc_namespace,
12087 test_default_ns_from_ext_subset_and_ext_ge);
12088 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_1);
12089 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_2);
12090 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_3);
12091 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_4);
12092 tcase_add_test(tc_namespace, test_ns_unbound_prefix);
12093 tcase_add_test(tc_namespace, test_ns_default_with_empty_uri);
12094 tcase_add_test(tc_namespace, test_ns_duplicate_attrs_diff_prefixes);
12095 tcase_add_test(tc_namespace, test_ns_duplicate_hashes);
12096 tcase_add_test(tc_namespace, test_ns_unbound_prefix_on_attribute);
12097 tcase_add_test(tc_namespace, test_ns_unbound_prefix_on_element);
12098 tcase_add_test(tc_namespace, test_ns_parser_reset);
12099 tcase_add_test(tc_namespace, test_ns_long_element);
12100 tcase_add_test(tc_namespace, test_ns_mixed_prefix_atts);
12101 tcase_add_test(tc_namespace, test_ns_extend_uri_buffer);
12102 tcase_add_test(tc_namespace, test_ns_reserved_attributes);
12103 tcase_add_test(tc_namespace, test_ns_reserved_attributes_2);
12104 tcase_add_test(tc_namespace, test_ns_extremely_long_prefix);
12105 tcase_add_test(tc_namespace, test_ns_unknown_encoding_success);
12106 tcase_add_test(tc_namespace, test_ns_double_colon);
12107 tcase_add_test(tc_namespace, test_ns_double_colon_element);
12108 tcase_add_test(tc_namespace, test_ns_bad_attr_leafname);
12109 tcase_add_test(tc_namespace, test_ns_bad_element_leafname);
12110 tcase_add_test(tc_namespace, test_ns_utf16_leafname);
12111 tcase_add_test(tc_namespace, test_ns_utf16_element_leafname);
12112 tcase_add_test(tc_namespace, test_ns_utf16_doctype);
12113 tcase_add_test(tc_namespace, test_ns_invalid_doctype);
12114 tcase_add_test(tc_namespace, test_ns_double_colon_doctype);
12115
12116 suite_add_tcase(s, tc_misc);
12117 tcase_add_checked_fixture(tc_misc, NULL, basic_teardown);
12118 tcase_add_test(tc_misc, test_misc_alloc_create_parser);
12119 tcase_add_test(tc_misc, test_misc_alloc_create_parser_with_encoding);
12120 tcase_add_test(tc_misc, test_misc_null_parser);
12121 tcase_add_test(tc_misc, test_misc_error_string);
12122 tcase_add_test(tc_misc, test_misc_version);
12123 tcase_add_test(tc_misc, test_misc_features);
12124 tcase_add_test(tc_misc, test_misc_attribute_leak);
12125 tcase_add_test(tc_misc, test_misc_utf16le);
12126 tcase_add_test(tc_misc, test_misc_stop_during_end_handler_issue_240_1);
12127 tcase_add_test(tc_misc, test_misc_stop_during_end_handler_issue_240_2);
12128 tcase_add_test__ifdef_xml_dtd(
12129 tc_misc, test_misc_deny_internal_entity_closing_doctype_issue_317);
12130
12131 suite_add_tcase(s, tc_alloc);
12132 tcase_add_checked_fixture(tc_alloc, alloc_setup, alloc_teardown);
12133 tcase_add_test(tc_alloc, test_alloc_parse_xdecl);
12134 tcase_add_test(tc_alloc, test_alloc_parse_xdecl_2);
12135 tcase_add_test(tc_alloc, test_alloc_parse_pi);
12136 tcase_add_test(tc_alloc, test_alloc_parse_pi_2);
12137 tcase_add_test(tc_alloc, test_alloc_parse_pi_3);
12138 tcase_add_test(tc_alloc, test_alloc_parse_comment);
12139 tcase_add_test(tc_alloc, test_alloc_parse_comment_2);
12140 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_create_external_parser);
12141 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_run_external_parser);
12142 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_dtd_copy_default_atts);
12143 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_external_entity);
12144 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_ext_entity_set_encoding);
12145 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_internal_entity);
12146 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_dtd_default_handling);
12147 tcase_add_test(tc_alloc, test_alloc_explicit_encoding);
12148 tcase_add_test(tc_alloc, test_alloc_set_base);
12149 tcase_add_test(tc_alloc, test_alloc_realloc_buffer);
12150 tcase_add_test(tc_alloc, test_alloc_ext_entity_realloc_buffer);
12151 tcase_add_test(tc_alloc, test_alloc_realloc_many_attributes);
12152 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_public_entity_value);
12153 tcase_add_test__ifdef_xml_dtd(tc_alloc,
12154 test_alloc_realloc_subst_public_entity_value);
12155 tcase_add_test(tc_alloc, test_alloc_parse_public_doctype);
12156 tcase_add_test(tc_alloc, test_alloc_parse_public_doctype_long_name);
12157 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_set_foreign_dtd);
12158 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_attribute_enum_value);
12159 tcase_add_test__ifdef_xml_dtd(tc_alloc,
12160 test_alloc_realloc_attribute_enum_value);
12161 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_implied_attribute);
12162 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_default_attribute);
12163 tcase_add_test(tc_alloc, test_alloc_notation);
12164 tcase_add_test(tc_alloc, test_alloc_public_notation);
12165 tcase_add_test(tc_alloc, test_alloc_system_notation);
12166 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_nested_groups);
12167 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_nested_groups);
12168 tcase_add_test(tc_alloc, test_alloc_large_group);
12169 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_group_choice);
12170 tcase_add_test(tc_alloc, test_alloc_pi_in_epilog);
12171 tcase_add_test(tc_alloc, test_alloc_comment_in_epilog);
12172 tcase_add_test__ifdef_xml_dtd(tc_alloc,
12173 test_alloc_realloc_long_attribute_value);
12174 tcase_add_test(tc_alloc, test_alloc_attribute_whitespace);
12175 tcase_add_test(tc_alloc, test_alloc_attribute_predefined_entity);
12176 tcase_add_test(tc_alloc, test_alloc_long_attr_default_with_char_ref);
12177 tcase_add_test(tc_alloc, test_alloc_long_attr_value);
12178 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_nested_entities);
12179 tcase_add_test__ifdef_xml_dtd(tc_alloc,
12180 test_alloc_realloc_param_entity_newline);
12181 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_ce_extends_pe);
12182 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_attributes);
12183 tcase_add_test(tc_alloc, test_alloc_long_doc_name);
12184 tcase_add_test(tc_alloc, test_alloc_long_base);
12185 tcase_add_test(tc_alloc, test_alloc_long_public_id);
12186 tcase_add_test(tc_alloc, test_alloc_long_entity_value);
12187 tcase_add_test(tc_alloc, test_alloc_long_notation);
12188 tcase_add_test__ifdef_xml_dtd(
12189 tc_alloc, test_alloc_reset_after_external_entity_parser_create_fail);
12190
12191 suite_add_tcase(s, tc_nsalloc);
12192 tcase_add_checked_fixture(tc_nsalloc, nsalloc_setup, nsalloc_teardown);
12193 tcase_add_test(tc_nsalloc, test_nsalloc_xmlns);
12194 tcase_add_test(tc_nsalloc, test_nsalloc_parse_buffer);
12195 tcase_add_test(tc_nsalloc, test_nsalloc_long_prefix);
12196 tcase_add_test(tc_nsalloc, test_nsalloc_long_uri);
12197 tcase_add_test(tc_nsalloc, test_nsalloc_long_attr);
12198 tcase_add_test(tc_nsalloc, test_nsalloc_long_attr_prefix);
12199 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_attributes);
12200 tcase_add_test(tc_nsalloc, test_nsalloc_long_element);
12201 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_binding_uri);
12202 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_prefix);
12203 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_longer_prefix);
12204 tcase_add_test(tc_nsalloc, test_nsalloc_long_namespace);
12205 tcase_add_test(tc_nsalloc, test_nsalloc_less_long_namespace);
12206 tcase_add_test(tc_nsalloc, test_nsalloc_long_context);
12207 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context);
12208 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_2);
12209 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_3);
12210 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_4);
12211 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_5);
12212 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_6);
12213 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_7);
12214 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_ge_name);
12215 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_in_dtd);
12216 tcase_add_test(tc_nsalloc, test_nsalloc_long_default_in_ext);
12217 tcase_add_test(tc_nsalloc, test_nsalloc_long_systemid_in_ext);
12218 tcase_add_test(tc_nsalloc, test_nsalloc_prefixed_element);
12219
12220 #if defined(XML_DTD)
12221 suite_add_tcase(s, tc_accounting);
12222 tcase_add_test(tc_accounting, test_accounting_precision);
12223 tcase_add_test(tc_accounting, test_billion_laughs_attack_protection_api);
12224 tcase_add_test(tc_accounting, test_helper_unsigned_char_to_printable);
12225 tcase_add_test__ifdef_xml_dtd(tc_accounting,
12226 test_amplification_isolated_external_parser);
12227 #endif
12228
12229 return s;
12230 }
12231
12232 int
main(int argc,char * argv[])12233 main(int argc, char *argv[]) {
12234 int i, nf;
12235 int verbosity = CK_NORMAL;
12236 Suite *s = make_suite();
12237 SRunner *sr = srunner_create(s);
12238
12239 /* run the tests for internal helper functions */
12240 testhelper_is_whitespace_normalized();
12241
12242 for (i = 1; i < argc; ++i) {
12243 char *opt = argv[i];
12244 if (strcmp(opt, "-v") == 0 || strcmp(opt, "--verbose") == 0)
12245 verbosity = CK_VERBOSE;
12246 else if (strcmp(opt, "-q") == 0 || strcmp(opt, "--quiet") == 0)
12247 verbosity = CK_SILENT;
12248 else {
12249 fprintf(stderr, "runtests: unknown option '%s'\n", opt);
12250 return 2;
12251 }
12252 }
12253 if (verbosity != CK_SILENT)
12254 printf("Expat version: %" XML_FMT_STR "\n", XML_ExpatVersion());
12255 srunner_run_all(sr, verbosity);
12256 nf = srunner_ntests_failed(sr);
12257 srunner_free(sr);
12258
12259 return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
12260 }
12261