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