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 <steven@solie.ca>
12 Copyright (c) 2005-2012 Karl Waclawek <karl@waclawek.net>
13 Copyright (c) 2016-2022 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 Copyright (c) 2021 Dong-hee Na <donghee.na@python.org>
21 Licensed under the MIT license:
22
23 Permission is hereby granted, free of charge, to any person obtaining
24 a copy of this software and associated documentation files (the
25 "Software"), to deal in the Software without restriction, including
26 without limitation the rights to use, copy, modify, merge, publish,
27 distribute, sublicense, and/or sell copies of the Software, and to permit
28 persons to whom the Software is furnished to do so, subject to the
29 following conditions:
30
31 The above copyright notice and this permission notice shall be included
32 in all copies or substantial portions of the Software.
33
34 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
35 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
36 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
37 NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
38 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
39 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
40 USE OR OTHER DEALINGS IN THE SOFTWARE.
41 */
42
43 #include <expat_config.h>
44
45 #if defined(NDEBUG)
46 # undef NDEBUG /* because test suite relies on assert(...) at the moment */
47 #endif
48
49 #include <assert.h>
50 #include <stdlib.h>
51 #include <stdio.h>
52 #include <string.h>
53 #include <stddef.h> /* ptrdiff_t */
54 #include <ctype.h>
55 #include <limits.h>
56 #include <stdint.h> /* intptr_t uint64_t */
57 #include <math.h> /* NAN, INFINITY, isnan */
58
59 #if ! defined(__cplusplus)
60 # include <stdbool.h>
61 #endif
62
63 #include "expat.h"
64 #include "chardata.h"
65 #include "structdata.h"
66 #include "internal.h"
67 #include "minicheck.h"
68 #include "memcheck.h"
69 #include "siphash.h"
70 #include "ascii.h" /* for ASCII_xxx */
71
72 #ifdef XML_LARGE_SIZE
73 # define XML_FMT_INT_MOD "ll"
74 #else
75 # define XML_FMT_INT_MOD "l"
76 #endif
77
78 #ifdef XML_UNICODE_WCHAR_T
79 # define XML_FMT_CHAR "lc"
80 # define XML_FMT_STR "ls"
81 # include <wchar.h>
82 # define xcstrlen(s) wcslen(s)
83 # define xcstrcmp(s, t) wcscmp((s), (t))
84 # define xcstrncmp(s, t, n) wcsncmp((s), (t), (n))
85 # define XCS(s) _XCS(s)
86 # define _XCS(s) L##s
87 #else
88 # ifdef XML_UNICODE
89 # error "No support for UTF-16 character without wchar_t in tests"
90 # else
91 # define XML_FMT_CHAR "c"
92 # define XML_FMT_STR "s"
93 # define xcstrlen(s) strlen(s)
94 # define xcstrcmp(s, t) strcmp((s), (t))
95 # define xcstrncmp(s, t, n) strncmp((s), (t), (n))
96 # define XCS(s) s
97 # endif /* XML_UNICODE */
98 #endif /* XML_UNICODE_WCHAR_T */
99
100 static XML_Parser g_parser = NULL;
101
102 static void
tcase_add_test__ifdef_xml_dtd(TCase * tc,tcase_test_function test)103 tcase_add_test__ifdef_xml_dtd(TCase *tc, tcase_test_function test) {
104 #ifdef XML_DTD
105 tcase_add_test(tc, test);
106 #else
107 UNUSED_P(tc);
108 UNUSED_P(test);
109 #endif
110 }
111
112 static void
basic_setup(void)113 basic_setup(void) {
114 g_parser = XML_ParserCreate(NULL);
115 if (g_parser == NULL)
116 fail("Parser not created.");
117 }
118
119 static void
basic_teardown(void)120 basic_teardown(void) {
121 if (g_parser != NULL) {
122 XML_ParserFree(g_parser);
123 g_parser = NULL;
124 }
125 }
126
127 /* Generate a failure using the parser state to create an error message;
128 this should be used when the parser reports an error we weren't
129 expecting.
130 */
131 static void
_xml_failure(XML_Parser parser,const char * file,int line)132 _xml_failure(XML_Parser parser, const char *file, int line) {
133 char buffer[1024];
134 enum XML_Error err = XML_GetErrorCode(parser);
135 sprintf(buffer,
136 " %d: %" XML_FMT_STR " (line %" XML_FMT_INT_MOD
137 "u, offset %" XML_FMT_INT_MOD "u)\n reported from %s, line %d\n",
138 err, XML_ErrorString(err), XML_GetCurrentLineNumber(parser),
139 XML_GetCurrentColumnNumber(parser), file, line);
140 _fail_unless(0, file, line, buffer);
141 }
142
143 static enum XML_Status
_XML_Parse_SINGLE_BYTES(XML_Parser parser,const char * s,int len,int isFinal)144 _XML_Parse_SINGLE_BYTES(XML_Parser parser, const char *s, int len,
145 int isFinal) {
146 enum XML_Status res = XML_STATUS_ERROR;
147 int offset = 0;
148
149 if (len == 0) {
150 return XML_Parse(parser, s, len, isFinal);
151 }
152
153 for (; offset < len; offset++) {
154 const int innerIsFinal = (offset == len - 1) && isFinal;
155 const char c = s[offset]; /* to help out-of-bounds detection */
156 res = XML_Parse(parser, &c, sizeof(char), innerIsFinal);
157 if (res != XML_STATUS_OK) {
158 return res;
159 }
160 }
161 return res;
162 }
163
164 #define xml_failure(parser) _xml_failure((parser), __FILE__, __LINE__)
165
166 static void
_expect_failure(const char * text,enum XML_Error errorCode,const char * errorMessage,const char * file,int lineno)167 _expect_failure(const char *text, enum XML_Error errorCode,
168 const char *errorMessage, const char *file, int lineno) {
169 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
170 == XML_STATUS_OK)
171 /* Hackish use of _fail_unless() macro, but let's us report
172 the right filename and line number. */
173 _fail_unless(0, file, lineno, errorMessage);
174 if (XML_GetErrorCode(g_parser) != errorCode)
175 _xml_failure(g_parser, file, lineno);
176 }
177
178 #define expect_failure(text, errorCode, errorMessage) \
179 _expect_failure((text), (errorCode), (errorMessage), __FILE__, __LINE__)
180
181 /* Dummy handlers for when we need to set a handler to tickle a bug,
182 but it doesn't need to do anything.
183 */
184 static unsigned long dummy_handler_flags = 0;
185
186 #define DUMMY_START_DOCTYPE_HANDLER_FLAG (1UL << 0)
187 #define DUMMY_END_DOCTYPE_HANDLER_FLAG (1UL << 1)
188 #define DUMMY_ENTITY_DECL_HANDLER_FLAG (1UL << 2)
189 #define DUMMY_NOTATION_DECL_HANDLER_FLAG (1UL << 3)
190 #define DUMMY_ELEMENT_DECL_HANDLER_FLAG (1UL << 4)
191 #define DUMMY_ATTLIST_DECL_HANDLER_FLAG (1UL << 5)
192 #define DUMMY_COMMENT_HANDLER_FLAG (1UL << 6)
193 #define DUMMY_PI_HANDLER_FLAG (1UL << 7)
194 #define DUMMY_START_ELEMENT_HANDLER_FLAG (1UL << 8)
195 #define DUMMY_START_CDATA_HANDLER_FLAG (1UL << 9)
196 #define DUMMY_END_CDATA_HANDLER_FLAG (1UL << 10)
197 #define DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG (1UL << 11)
198 #define DUMMY_START_NS_DECL_HANDLER_FLAG (1UL << 12)
199 #define DUMMY_END_NS_DECL_HANDLER_FLAG (1UL << 13)
200 #define DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG (1UL << 14)
201 #define DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG (1UL << 15)
202 #define DUMMY_SKIP_HANDLER_FLAG (1UL << 16)
203 #define DUMMY_DEFAULT_HANDLER_FLAG (1UL << 17)
204
205 static void XMLCALL
dummy_xdecl_handler(void * userData,const XML_Char * version,const XML_Char * encoding,int standalone)206 dummy_xdecl_handler(void *userData, const XML_Char *version,
207 const XML_Char *encoding, int standalone) {
208 UNUSED_P(userData);
209 UNUSED_P(version);
210 UNUSED_P(encoding);
211 UNUSED_P(standalone);
212 }
213
214 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)215 dummy_start_doctype_handler(void *userData, const XML_Char *doctypeName,
216 const XML_Char *sysid, const XML_Char *pubid,
217 int has_internal_subset) {
218 UNUSED_P(userData);
219 UNUSED_P(doctypeName);
220 UNUSED_P(sysid);
221 UNUSED_P(pubid);
222 UNUSED_P(has_internal_subset);
223 dummy_handler_flags |= DUMMY_START_DOCTYPE_HANDLER_FLAG;
224 }
225
226 static void XMLCALL
dummy_end_doctype_handler(void * userData)227 dummy_end_doctype_handler(void *userData) {
228 UNUSED_P(userData);
229 dummy_handler_flags |= DUMMY_END_DOCTYPE_HANDLER_FLAG;
230 }
231
232 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)233 dummy_entity_decl_handler(void *userData, const XML_Char *entityName,
234 int is_parameter_entity, const XML_Char *value,
235 int value_length, const XML_Char *base,
236 const XML_Char *systemId, const XML_Char *publicId,
237 const XML_Char *notationName) {
238 UNUSED_P(userData);
239 UNUSED_P(entityName);
240 UNUSED_P(is_parameter_entity);
241 UNUSED_P(value);
242 UNUSED_P(value_length);
243 UNUSED_P(base);
244 UNUSED_P(systemId);
245 UNUSED_P(publicId);
246 UNUSED_P(notationName);
247 dummy_handler_flags |= DUMMY_ENTITY_DECL_HANDLER_FLAG;
248 }
249
250 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)251 dummy_notation_decl_handler(void *userData, const XML_Char *notationName,
252 const XML_Char *base, const XML_Char *systemId,
253 const XML_Char *publicId) {
254 UNUSED_P(userData);
255 UNUSED_P(notationName);
256 UNUSED_P(base);
257 UNUSED_P(systemId);
258 UNUSED_P(publicId);
259 dummy_handler_flags |= DUMMY_NOTATION_DECL_HANDLER_FLAG;
260 }
261
262 static void XMLCALL
dummy_element_decl_handler(void * userData,const XML_Char * name,XML_Content * model)263 dummy_element_decl_handler(void *userData, const XML_Char *name,
264 XML_Content *model) {
265 UNUSED_P(userData);
266 UNUSED_P(name);
267 /* The content model must be freed by the handler. Unfortunately
268 * we cannot pass the parser as the userData because this is used
269 * with other handlers that require other userData.
270 */
271 XML_FreeContentModel(g_parser, model);
272 dummy_handler_flags |= DUMMY_ELEMENT_DECL_HANDLER_FLAG;
273 }
274
275 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)276 dummy_attlist_decl_handler(void *userData, const XML_Char *elname,
277 const XML_Char *attname, const XML_Char *att_type,
278 const XML_Char *dflt, int isrequired) {
279 UNUSED_P(userData);
280 UNUSED_P(elname);
281 UNUSED_P(attname);
282 UNUSED_P(att_type);
283 UNUSED_P(dflt);
284 UNUSED_P(isrequired);
285 dummy_handler_flags |= DUMMY_ATTLIST_DECL_HANDLER_FLAG;
286 }
287
288 static void XMLCALL
dummy_comment_handler(void * userData,const XML_Char * data)289 dummy_comment_handler(void *userData, const XML_Char *data) {
290 UNUSED_P(userData);
291 UNUSED_P(data);
292 dummy_handler_flags |= DUMMY_COMMENT_HANDLER_FLAG;
293 }
294
295 static void XMLCALL
dummy_pi_handler(void * userData,const XML_Char * target,const XML_Char * data)296 dummy_pi_handler(void *userData, const XML_Char *target, const XML_Char *data) {
297 UNUSED_P(userData);
298 UNUSED_P(target);
299 UNUSED_P(data);
300 dummy_handler_flags |= DUMMY_PI_HANDLER_FLAG;
301 }
302
303 static void XMLCALL
dummy_start_element(void * userData,const XML_Char * name,const XML_Char ** atts)304 dummy_start_element(void *userData, const XML_Char *name,
305 const XML_Char **atts) {
306 UNUSED_P(userData);
307 UNUSED_P(name);
308 UNUSED_P(atts);
309 dummy_handler_flags |= DUMMY_START_ELEMENT_HANDLER_FLAG;
310 }
311
312 static void XMLCALL
dummy_end_element(void * userData,const XML_Char * name)313 dummy_end_element(void *userData, const XML_Char *name) {
314 UNUSED_P(userData);
315 UNUSED_P(name);
316 }
317
318 static void XMLCALL
dummy_start_cdata_handler(void * userData)319 dummy_start_cdata_handler(void *userData) {
320 UNUSED_P(userData);
321 dummy_handler_flags |= DUMMY_START_CDATA_HANDLER_FLAG;
322 }
323
324 static void XMLCALL
dummy_end_cdata_handler(void * userData)325 dummy_end_cdata_handler(void *userData) {
326 UNUSED_P(userData);
327 dummy_handler_flags |= DUMMY_END_CDATA_HANDLER_FLAG;
328 }
329
330 static void XMLCALL
dummy_cdata_handler(void * userData,const XML_Char * s,int len)331 dummy_cdata_handler(void *userData, const XML_Char *s, int len) {
332 UNUSED_P(userData);
333 UNUSED_P(s);
334 UNUSED_P(len);
335 }
336
337 static void XMLCALL
dummy_start_namespace_decl_handler(void * userData,const XML_Char * prefix,const XML_Char * uri)338 dummy_start_namespace_decl_handler(void *userData, const XML_Char *prefix,
339 const XML_Char *uri) {
340 UNUSED_P(userData);
341 UNUSED_P(prefix);
342 UNUSED_P(uri);
343 dummy_handler_flags |= DUMMY_START_NS_DECL_HANDLER_FLAG;
344 }
345
346 static void XMLCALL
dummy_end_namespace_decl_handler(void * userData,const XML_Char * prefix)347 dummy_end_namespace_decl_handler(void *userData, const XML_Char *prefix) {
348 UNUSED_P(userData);
349 UNUSED_P(prefix);
350 dummy_handler_flags |= DUMMY_END_NS_DECL_HANDLER_FLAG;
351 }
352
353 /* This handler is obsolete, but while the code exists we should
354 * ensure that dealing with the handler is covered by tests.
355 */
356 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)357 dummy_unparsed_entity_decl_handler(void *userData, const XML_Char *entityName,
358 const XML_Char *base,
359 const XML_Char *systemId,
360 const XML_Char *publicId,
361 const XML_Char *notationName) {
362 UNUSED_P(userData);
363 UNUSED_P(entityName);
364 UNUSED_P(base);
365 UNUSED_P(systemId);
366 UNUSED_P(publicId);
367 UNUSED_P(notationName);
368 dummy_handler_flags |= DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG;
369 }
370
371 static void XMLCALL
dummy_default_handler(void * userData,const XML_Char * s,int len)372 dummy_default_handler(void *userData, const XML_Char *s, int len) {
373 UNUSED_P(userData);
374 UNUSED_P(s);
375 UNUSED_P(len);
376 }
377
378 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)379 dummy_start_doctype_decl_handler(void *userData, const XML_Char *doctypeName,
380 const XML_Char *sysid, const XML_Char *pubid,
381 int has_internal_subset) {
382 UNUSED_P(userData);
383 UNUSED_P(doctypeName);
384 UNUSED_P(sysid);
385 UNUSED_P(pubid);
386 UNUSED_P(has_internal_subset);
387 dummy_handler_flags |= DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG;
388 }
389
390 static void XMLCALL
dummy_end_doctype_decl_handler(void * userData)391 dummy_end_doctype_decl_handler(void *userData) {
392 UNUSED_P(userData);
393 dummy_handler_flags |= DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG;
394 }
395
396 static void XMLCALL
dummy_skip_handler(void * userData,const XML_Char * entityName,int is_parameter_entity)397 dummy_skip_handler(void *userData, const XML_Char *entityName,
398 int is_parameter_entity) {
399 UNUSED_P(userData);
400 UNUSED_P(entityName);
401 UNUSED_P(is_parameter_entity);
402 dummy_handler_flags |= DUMMY_SKIP_HANDLER_FLAG;
403 }
404
405 /* Useful external entity handler */
406 typedef struct ExtOption {
407 const XML_Char *system_id;
408 const char *parse_text;
409 } ExtOption;
410
411 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)412 external_entity_optioner(XML_Parser parser, const XML_Char *context,
413 const XML_Char *base, const XML_Char *systemId,
414 const XML_Char *publicId) {
415 ExtOption *options = (ExtOption *)XML_GetUserData(parser);
416 XML_Parser ext_parser;
417
418 UNUSED_P(base);
419 UNUSED_P(publicId);
420 while (options->parse_text != NULL) {
421 if (! xcstrcmp(systemId, options->system_id)) {
422 enum XML_Status rc;
423 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
424 if (ext_parser == NULL)
425 return XML_STATUS_ERROR;
426 rc = _XML_Parse_SINGLE_BYTES(ext_parser, options->parse_text,
427 (int)strlen(options->parse_text), XML_TRUE);
428 XML_ParserFree(ext_parser);
429 return rc;
430 }
431 options++;
432 }
433 fail("No suitable option found");
434 return XML_STATUS_ERROR;
435 }
436
437 /*
438 * Parameter entity evaluation support.
439 */
440 #define ENTITY_MATCH_FAIL (-1)
441 #define ENTITY_MATCH_NOT_FOUND (0)
442 #define ENTITY_MATCH_SUCCESS (1)
443 static const XML_Char *entity_name_to_match = NULL;
444 static const XML_Char *entity_value_to_match = NULL;
445 static int entity_match_flag = ENTITY_MATCH_NOT_FOUND;
446
447 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)448 param_entity_match_handler(void *userData, const XML_Char *entityName,
449 int is_parameter_entity, const XML_Char *value,
450 int value_length, const XML_Char *base,
451 const XML_Char *systemId, const XML_Char *publicId,
452 const XML_Char *notationName) {
453 UNUSED_P(userData);
454 UNUSED_P(base);
455 UNUSED_P(systemId);
456 UNUSED_P(publicId);
457 UNUSED_P(notationName);
458 if (! is_parameter_entity || entity_name_to_match == NULL
459 || entity_value_to_match == NULL) {
460 return;
461 }
462 if (! xcstrcmp(entityName, entity_name_to_match)) {
463 /* The cast here is safe because we control the horizontal and
464 * the vertical, and we therefore know our strings are never
465 * going to overflow an int.
466 */
467 if (value_length != (int)xcstrlen(entity_value_to_match)
468 || xcstrncmp(value, entity_value_to_match, value_length)) {
469 entity_match_flag = ENTITY_MATCH_FAIL;
470 } else {
471 entity_match_flag = ENTITY_MATCH_SUCCESS;
472 }
473 }
474 /* Else leave the match flag alone */
475 }
476
477 /*
478 * Character & encoding tests.
479 */
480
START_TEST(test_nul_byte)481 START_TEST(test_nul_byte) {
482 char text[] = "<doc>\0</doc>";
483
484 /* test that a NUL byte (in US-ASCII data) is an error */
485 if (_XML_Parse_SINGLE_BYTES(g_parser, text, sizeof(text) - 1, XML_TRUE)
486 == XML_STATUS_OK)
487 fail("Parser did not report error on NUL-byte.");
488 if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
489 xml_failure(g_parser);
490 }
491 END_TEST
492
START_TEST(test_u0000_char)493 START_TEST(test_u0000_char) {
494 /* test that a NUL byte (in US-ASCII data) is an error */
495 expect_failure("<doc>�</doc>", XML_ERROR_BAD_CHAR_REF,
496 "Parser did not report error on NUL-byte.");
497 }
498 END_TEST
499
START_TEST(test_siphash_self)500 START_TEST(test_siphash_self) {
501 if (! sip24_valid())
502 fail("SipHash self-test failed");
503 }
504 END_TEST
505
START_TEST(test_siphash_spec)506 START_TEST(test_siphash_spec) {
507 /* https://131002.net/siphash/siphash.pdf (page 19, "Test values") */
508 const char message[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09"
509 "\x0a\x0b\x0c\x0d\x0e";
510 const size_t len = sizeof(message) - 1;
511 const uint64_t expected = _SIP_ULL(0xa129ca61U, 0x49be45e5U);
512 struct siphash state;
513 struct sipkey key;
514
515 sip_tokey(&key, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09"
516 "\x0a\x0b\x0c\x0d\x0e\x0f");
517 sip24_init(&state, &key);
518
519 /* Cover spread across calls */
520 sip24_update(&state, message, 4);
521 sip24_update(&state, message + 4, len - 4);
522
523 /* Cover null length */
524 sip24_update(&state, message, 0);
525
526 if (sip24_final(&state) != expected)
527 fail("sip24_final failed spec test\n");
528
529 /* Cover wrapper */
530 if (siphash24(message, len, &key) != expected)
531 fail("siphash24 failed spec test\n");
532 }
533 END_TEST
534
START_TEST(test_bom_utf8)535 START_TEST(test_bom_utf8) {
536 /* This test is really just making sure we don't core on a UTF-8 BOM. */
537 const char *text = "\357\273\277<e/>";
538
539 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
540 == XML_STATUS_ERROR)
541 xml_failure(g_parser);
542 }
543 END_TEST
544
START_TEST(test_bom_utf16_be)545 START_TEST(test_bom_utf16_be) {
546 char text[] = "\376\377\0<\0e\0/\0>";
547
548 if (_XML_Parse_SINGLE_BYTES(g_parser, text, sizeof(text) - 1, XML_TRUE)
549 == XML_STATUS_ERROR)
550 xml_failure(g_parser);
551 }
552 END_TEST
553
START_TEST(test_bom_utf16_le)554 START_TEST(test_bom_utf16_le) {
555 char text[] = "\377\376<\0e\0/\0>\0";
556
557 if (_XML_Parse_SINGLE_BYTES(g_parser, text, sizeof(text) - 1, XML_TRUE)
558 == XML_STATUS_ERROR)
559 xml_failure(g_parser);
560 }
561 END_TEST
562
563 /* Parse whole buffer at once to exercise a different code path */
START_TEST(test_nobom_utf16_le)564 START_TEST(test_nobom_utf16_le) {
565 char text[] = " \0<\0e\0/\0>\0";
566
567 if (XML_Parse(g_parser, text, sizeof(text) - 1, XML_TRUE) == XML_STATUS_ERROR)
568 xml_failure(g_parser);
569 }
570 END_TEST
571
572 static void XMLCALL
accumulate_characters(void * userData,const XML_Char * s,int len)573 accumulate_characters(void *userData, const XML_Char *s, int len) {
574 CharData_AppendXMLChars((CharData *)userData, s, len);
575 }
576
577 static void XMLCALL
accumulate_attribute(void * userData,const XML_Char * name,const XML_Char ** atts)578 accumulate_attribute(void *userData, const XML_Char *name,
579 const XML_Char **atts) {
580 CharData *storage = (CharData *)userData;
581 UNUSED_P(name);
582 /* Check there are attributes to deal with */
583 if (atts == NULL)
584 return;
585
586 while (storage->count < 0 && atts[0] != NULL) {
587 /* "accumulate" the value of the first attribute we see */
588 CharData_AppendXMLChars(storage, atts[1], -1);
589 atts += 2;
590 }
591 }
592
593 static void
_run_character_check(const char * text,const XML_Char * expected,const char * file,int line)594 _run_character_check(const char *text, const XML_Char *expected,
595 const char *file, int line) {
596 CharData storage;
597
598 CharData_Init(&storage);
599 XML_SetUserData(g_parser, &storage);
600 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
601 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
602 == XML_STATUS_ERROR)
603 _xml_failure(g_parser, file, line);
604 CharData_CheckXMLChars(&storage, expected);
605 }
606
607 #define run_character_check(text, expected) \
608 _run_character_check(text, expected, __FILE__, __LINE__)
609
610 static void
_run_attribute_check(const char * text,const XML_Char * expected,const char * file,int line)611 _run_attribute_check(const char *text, const XML_Char *expected,
612 const char *file, int line) {
613 CharData storage;
614
615 CharData_Init(&storage);
616 XML_SetUserData(g_parser, &storage);
617 XML_SetStartElementHandler(g_parser, accumulate_attribute);
618 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
619 == XML_STATUS_ERROR)
620 _xml_failure(g_parser, file, line);
621 CharData_CheckXMLChars(&storage, expected);
622 }
623
624 #define run_attribute_check(text, expected) \
625 _run_attribute_check(text, expected, __FILE__, __LINE__)
626
627 typedef struct ExtTest {
628 const char *parse_text;
629 const XML_Char *encoding;
630 CharData *storage;
631 } ExtTest;
632
633 static void XMLCALL
ext_accumulate_characters(void * userData,const XML_Char * s,int len)634 ext_accumulate_characters(void *userData, const XML_Char *s, int len) {
635 ExtTest *test_data = (ExtTest *)userData;
636 accumulate_characters(test_data->storage, s, len);
637 }
638
639 static void
_run_ext_character_check(const char * text,ExtTest * test_data,const XML_Char * expected,const char * file,int line)640 _run_ext_character_check(const char *text, ExtTest *test_data,
641 const XML_Char *expected, const char *file, int line) {
642 CharData *const storage = (CharData *)malloc(sizeof(CharData));
643
644 CharData_Init(storage);
645 test_data->storage = storage;
646 XML_SetUserData(g_parser, test_data);
647 XML_SetCharacterDataHandler(g_parser, ext_accumulate_characters);
648 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
649 == XML_STATUS_ERROR)
650 _xml_failure(g_parser, file, line);
651 CharData_CheckXMLChars(storage, expected);
652
653 free(storage);
654 }
655
656 #define run_ext_character_check(text, test_data, expected) \
657 _run_ext_character_check(text, test_data, expected, __FILE__, __LINE__)
658
659 /* Regression test for SF bug #491986. */
START_TEST(test_danish_latin1)660 START_TEST(test_danish_latin1) {
661 const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
662 "<e>J\xF8rgen \xE6\xF8\xE5\xC6\xD8\xC5</e>";
663 #ifdef XML_UNICODE
664 const XML_Char *expected
665 = XCS("J\x00f8rgen \x00e6\x00f8\x00e5\x00c6\x00d8\x00c5");
666 #else
667 const XML_Char *expected
668 = XCS("J\xC3\xB8rgen \xC3\xA6\xC3\xB8\xC3\xA5\xC3\x86\xC3\x98\xC3\x85");
669 #endif
670 run_character_check(text, expected);
671 }
672 END_TEST
673
674 /* Regression test for SF bug #514281. */
START_TEST(test_french_charref_hexidecimal)675 START_TEST(test_french_charref_hexidecimal) {
676 const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
677 "<doc>éèàçêÈ</doc>";
678 #ifdef XML_UNICODE
679 const XML_Char *expected = XCS("\x00e9\x00e8\x00e0\x00e7\x00ea\x00c8");
680 #else
681 const XML_Char *expected
682 = XCS("\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88");
683 #endif
684 run_character_check(text, expected);
685 }
686 END_TEST
687
START_TEST(test_french_charref_decimal)688 START_TEST(test_french_charref_decimal) {
689 const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
690 "<doc>éèàçêÈ</doc>";
691 #ifdef XML_UNICODE
692 const XML_Char *expected = XCS("\x00e9\x00e8\x00e0\x00e7\x00ea\x00c8");
693 #else
694 const XML_Char *expected
695 = XCS("\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88");
696 #endif
697 run_character_check(text, expected);
698 }
699 END_TEST
700
START_TEST(test_french_latin1)701 START_TEST(test_french_latin1) {
702 const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
703 "<doc>\xE9\xE8\xE0\xE7\xEa\xC8</doc>";
704 #ifdef XML_UNICODE
705 const XML_Char *expected = XCS("\x00e9\x00e8\x00e0\x00e7\x00ea\x00c8");
706 #else
707 const XML_Char *expected
708 = XCS("\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88");
709 #endif
710 run_character_check(text, expected);
711 }
712 END_TEST
713
START_TEST(test_french_utf8)714 START_TEST(test_french_utf8) {
715 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
716 "<doc>\xC3\xA9</doc>";
717 #ifdef XML_UNICODE
718 const XML_Char *expected = XCS("\x00e9");
719 #else
720 const XML_Char *expected = XCS("\xC3\xA9");
721 #endif
722 run_character_check(text, expected);
723 }
724 END_TEST
725
726 /* Regression test for SF bug #600479.
727 XXX There should be a test that exercises all legal XML Unicode
728 characters as PCDATA and attribute value content, and XML Name
729 characters as part of element and attribute names.
730 */
START_TEST(test_utf8_false_rejection)731 START_TEST(test_utf8_false_rejection) {
732 const char *text = "<doc>\xEF\xBA\xBF</doc>";
733 #ifdef XML_UNICODE
734 const XML_Char *expected = XCS("\xfebf");
735 #else
736 const XML_Char *expected = XCS("\xEF\xBA\xBF");
737 #endif
738 run_character_check(text, expected);
739 }
740 END_TEST
741
742 /* Regression test for SF bug #477667.
743 This test assures that any 8-bit character followed by a 7-bit
744 character will not be mistakenly interpreted as a valid UTF-8
745 sequence.
746 */
START_TEST(test_illegal_utf8)747 START_TEST(test_illegal_utf8) {
748 char text[100];
749 int i;
750
751 for (i = 128; i <= 255; ++i) {
752 sprintf(text, "<e>%ccd</e>", i);
753 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
754 == XML_STATUS_OK) {
755 sprintf(text, "expected token error for '%c' (ordinal %d) in UTF-8 text",
756 i, i);
757 fail(text);
758 } else if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
759 xml_failure(g_parser);
760 /* Reset the parser since we use the same parser repeatedly. */
761 XML_ParserReset(g_parser, NULL);
762 }
763 }
764 END_TEST
765
766 /* Examples, not masks: */
767 #define UTF8_LEAD_1 "\x7f" /* 0b01111111 */
768 #define UTF8_LEAD_2 "\xdf" /* 0b11011111 */
769 #define UTF8_LEAD_3 "\xef" /* 0b11101111 */
770 #define UTF8_LEAD_4 "\xf7" /* 0b11110111 */
771 #define UTF8_FOLLOW "\xbf" /* 0b10111111 */
772
START_TEST(test_utf8_auto_align)773 START_TEST(test_utf8_auto_align) {
774 struct TestCase {
775 ptrdiff_t expectedMovementInChars;
776 const char *input;
777 };
778
779 struct TestCase cases[] = {
780 {00, ""},
781
782 {00, UTF8_LEAD_1},
783
784 {-1, UTF8_LEAD_2},
785 {00, UTF8_LEAD_2 UTF8_FOLLOW},
786
787 {-1, UTF8_LEAD_3},
788 {-2, UTF8_LEAD_3 UTF8_FOLLOW},
789 {00, UTF8_LEAD_3 UTF8_FOLLOW UTF8_FOLLOW},
790
791 {-1, UTF8_LEAD_4},
792 {-2, UTF8_LEAD_4 UTF8_FOLLOW},
793 {-3, UTF8_LEAD_4 UTF8_FOLLOW UTF8_FOLLOW},
794 {00, UTF8_LEAD_4 UTF8_FOLLOW UTF8_FOLLOW UTF8_FOLLOW},
795 };
796
797 size_t i = 0;
798 bool success = true;
799 for (; i < sizeof(cases) / sizeof(*cases); i++) {
800 const char *fromLim = cases[i].input + strlen(cases[i].input);
801 const char *const fromLimInitially = fromLim;
802 ptrdiff_t actualMovementInChars;
803
804 _INTERNAL_trim_to_complete_utf8_characters(cases[i].input, &fromLim);
805
806 actualMovementInChars = (fromLim - fromLimInitially);
807 if (actualMovementInChars != cases[i].expectedMovementInChars) {
808 size_t j = 0;
809 success = false;
810 printf("[-] UTF-8 case %2u: Expected movement by %2d chars"
811 ", actually moved by %2d chars: \"",
812 (unsigned)(i + 1), (int)cases[i].expectedMovementInChars,
813 (int)actualMovementInChars);
814 for (; j < strlen(cases[i].input); j++) {
815 printf("\\x%02x", (unsigned char)cases[i].input[j]);
816 }
817 printf("\"\n");
818 }
819 }
820
821 if (! success) {
822 fail("UTF-8 auto-alignment is not bullet-proof\n");
823 }
824 }
825 END_TEST
826
START_TEST(test_utf16)827 START_TEST(test_utf16) {
828 /* <?xml version="1.0" encoding="UTF-16"?>
829 * <doc a='123'>some {A} text</doc>
830 *
831 * where {A} is U+FF21, FULLWIDTH LATIN CAPITAL LETTER A
832 */
833 char text[]
834 = "\000<\000?\000x\000m\000\154\000 \000v\000e\000r\000s\000i\000o"
835 "\000n\000=\000'\0001\000.\000\060\000'\000 \000e\000n\000c\000o"
836 "\000d\000i\000n\000g\000=\000'\000U\000T\000F\000-\0001\000\066"
837 "\000'\000?\000>\000\n"
838 "\000<\000d\000o\000c\000 \000a\000=\000'\0001\0002\0003\000'\000>"
839 "\000s\000o\000m\000e\000 \xff\x21\000 \000t\000e\000x\000t\000"
840 "<\000/\000d\000o\000c\000>";
841 #ifdef XML_UNICODE
842 const XML_Char *expected = XCS("some \xff21 text");
843 #else
844 const XML_Char *expected = XCS("some \357\274\241 text");
845 #endif
846 CharData storage;
847
848 CharData_Init(&storage);
849 XML_SetUserData(g_parser, &storage);
850 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
851 if (_XML_Parse_SINGLE_BYTES(g_parser, text, sizeof(text) - 1, XML_TRUE)
852 == XML_STATUS_ERROR)
853 xml_failure(g_parser);
854 CharData_CheckXMLChars(&storage, expected);
855 }
856 END_TEST
857
START_TEST(test_utf16_le_epilog_newline)858 START_TEST(test_utf16_le_epilog_newline) {
859 unsigned int first_chunk_bytes = 17;
860 char text[] = "\xFF\xFE" /* BOM */
861 "<\000e\000/\000>\000" /* document element */
862 "\r\000\n\000\r\000\n\000"; /* epilog */
863
864 if (first_chunk_bytes >= sizeof(text) - 1)
865 fail("bad value of first_chunk_bytes");
866 if (_XML_Parse_SINGLE_BYTES(g_parser, text, first_chunk_bytes, XML_FALSE)
867 == XML_STATUS_ERROR)
868 xml_failure(g_parser);
869 else {
870 enum XML_Status rc;
871 rc = _XML_Parse_SINGLE_BYTES(g_parser, text + first_chunk_bytes,
872 sizeof(text) - first_chunk_bytes - 1,
873 XML_TRUE);
874 if (rc == XML_STATUS_ERROR)
875 xml_failure(g_parser);
876 }
877 }
878 END_TEST
879
880 /* Test that an outright lie in the encoding is faulted */
START_TEST(test_not_utf16)881 START_TEST(test_not_utf16) {
882 const char *text = "<?xml version='1.0' encoding='utf-16'?>"
883 "<doc>Hi</doc>";
884
885 /* Use a handler to provoke the appropriate code paths */
886 XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler);
887 expect_failure(text, XML_ERROR_INCORRECT_ENCODING,
888 "UTF-16 declared in UTF-8 not faulted");
889 }
890 END_TEST
891
892 /* Test that an unknown encoding is rejected */
START_TEST(test_bad_encoding)893 START_TEST(test_bad_encoding) {
894 const char *text = "<doc>Hi</doc>";
895
896 if (! XML_SetEncoding(g_parser, XCS("unknown-encoding")))
897 fail("XML_SetEncoding failed");
898 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
899 "Unknown encoding not faulted");
900 }
901 END_TEST
902
903 /* Regression test for SF bug #481609, #774028. */
START_TEST(test_latin1_umlauts)904 START_TEST(test_latin1_umlauts) {
905 const char *text
906 = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
907 "<e a='\xE4 \xF6 \xFC ä ö ü ä ö ü >'\n"
908 " >\xE4 \xF6 \xFC ä ö ü ä ö ü ></e>";
909 #ifdef XML_UNICODE
910 /* Expected results in UTF-16 */
911 const XML_Char *expected = XCS("\x00e4 \x00f6 \x00fc ")
912 XCS("\x00e4 \x00f6 \x00fc ") XCS("\x00e4 \x00f6 \x00fc >");
913 #else
914 /* Expected results in UTF-8 */
915 const XML_Char *expected = XCS("\xC3\xA4 \xC3\xB6 \xC3\xBC ")
916 XCS("\xC3\xA4 \xC3\xB6 \xC3\xBC ") XCS("\xC3\xA4 \xC3\xB6 \xC3\xBC >");
917 #endif
918
919 run_character_check(text, expected);
920 XML_ParserReset(g_parser, NULL);
921 run_attribute_check(text, expected);
922 /* Repeat with a default handler */
923 XML_ParserReset(g_parser, NULL);
924 XML_SetDefaultHandler(g_parser, dummy_default_handler);
925 run_character_check(text, expected);
926 XML_ParserReset(g_parser, NULL);
927 XML_SetDefaultHandler(g_parser, dummy_default_handler);
928 run_attribute_check(text, expected);
929 }
930 END_TEST
931
932 /* Test that an element name with a 4-byte UTF-8 character is rejected */
START_TEST(test_long_utf8_character)933 START_TEST(test_long_utf8_character) {
934 const char *text
935 = "<?xml version='1.0' encoding='utf-8'?>\n"
936 /* 0xf0 0x90 0x80 0x80 = U+10000, the first Linear B character */
937 "<do\xf0\x90\x80\x80/>";
938 expect_failure(text, XML_ERROR_INVALID_TOKEN,
939 "4-byte UTF-8 character in element name not faulted");
940 }
941 END_TEST
942
943 /* Test that a long latin-1 attribute (too long to convert in one go)
944 * is correctly converted
945 */
START_TEST(test_long_latin1_attribute)946 START_TEST(test_long_latin1_attribute) {
947 const char *text
948 = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
949 "<doc att='"
950 /* 64 characters per line */
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 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
966 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
967 /* Last character splits across a buffer boundary */
968 "\xe4'>\n</doc>";
969
970 const XML_Char *expected =
971 /* 64 characters per line */
972 /* clang-format off */
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("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
988 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO")
989 /* clang-format on */
990 #ifdef XML_UNICODE
991 XCS("\x00e4");
992 #else
993 XCS("\xc3\xa4");
994 #endif
995
996 run_attribute_check(text, expected);
997 }
998 END_TEST
999
1000 /* Test that a long ASCII attribute (too long to convert in one go)
1001 * is correctly converted
1002 */
START_TEST(test_long_ascii_attribute)1003 START_TEST(test_long_ascii_attribute) {
1004 const char *text
1005 = "<?xml version='1.0' encoding='us-ascii'?>\n"
1006 "<doc att='"
1007 /* 64 characters per line */
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 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1024 "01234'>\n</doc>";
1025 const XML_Char *expected =
1026 /* 64 characters per line */
1027 /* clang-format off */
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("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1044 XCS("01234");
1045 /* clang-format on */
1046
1047 run_attribute_check(text, expected);
1048 }
1049 END_TEST
1050
1051 /* Regression test #1 for SF bug #653180. */
START_TEST(test_line_number_after_parse)1052 START_TEST(test_line_number_after_parse) {
1053 const char *text = "<tag>\n"
1054 "\n"
1055 "\n</tag>";
1056 XML_Size lineno;
1057
1058 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
1059 == XML_STATUS_ERROR)
1060 xml_failure(g_parser);
1061 lineno = XML_GetCurrentLineNumber(g_parser);
1062 if (lineno != 4) {
1063 char buffer[100];
1064 sprintf(buffer, "expected 4 lines, saw %" XML_FMT_INT_MOD "u", lineno);
1065 fail(buffer);
1066 }
1067 }
1068 END_TEST
1069
1070 /* Regression test #2 for SF bug #653180. */
START_TEST(test_column_number_after_parse)1071 START_TEST(test_column_number_after_parse) {
1072 const char *text = "<tag></tag>";
1073 XML_Size colno;
1074
1075 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
1076 == XML_STATUS_ERROR)
1077 xml_failure(g_parser);
1078 colno = XML_GetCurrentColumnNumber(g_parser);
1079 if (colno != 11) {
1080 char buffer[100];
1081 sprintf(buffer, "expected 11 columns, saw %" XML_FMT_INT_MOD "u", colno);
1082 fail(buffer);
1083 }
1084 }
1085 END_TEST
1086
1087 #define STRUCT_START_TAG 0
1088 #define STRUCT_END_TAG 1
1089 static void XMLCALL
start_element_event_handler2(void * userData,const XML_Char * name,const XML_Char ** attr)1090 start_element_event_handler2(void *userData, const XML_Char *name,
1091 const XML_Char **attr) {
1092 StructData *storage = (StructData *)userData;
1093 UNUSED_P(attr);
1094 StructData_AddItem(storage, name, XML_GetCurrentColumnNumber(g_parser),
1095 XML_GetCurrentLineNumber(g_parser), STRUCT_START_TAG);
1096 }
1097
1098 static void XMLCALL
end_element_event_handler2(void * userData,const XML_Char * name)1099 end_element_event_handler2(void *userData, const XML_Char *name) {
1100 StructData *storage = (StructData *)userData;
1101 StructData_AddItem(storage, name, XML_GetCurrentColumnNumber(g_parser),
1102 XML_GetCurrentLineNumber(g_parser), STRUCT_END_TAG);
1103 }
1104
1105 /* Regression test #3 for SF bug #653180. */
START_TEST(test_line_and_column_numbers_inside_handlers)1106 START_TEST(test_line_and_column_numbers_inside_handlers) {
1107 const char *text = "<a>\n" /* Unix end-of-line */
1108 " <b>\r\n" /* Windows end-of-line */
1109 " <c/>\r" /* Mac OS end-of-line */
1110 " </b>\n"
1111 " <d>\n"
1112 " <f/>\n"
1113 " </d>\n"
1114 "</a>";
1115 const StructDataEntry expected[]
1116 = {{XCS("a"), 0, 1, STRUCT_START_TAG}, {XCS("b"), 2, 2, STRUCT_START_TAG},
1117 {XCS("c"), 4, 3, STRUCT_START_TAG}, {XCS("c"), 8, 3, STRUCT_END_TAG},
1118 {XCS("b"), 2, 4, STRUCT_END_TAG}, {XCS("d"), 2, 5, STRUCT_START_TAG},
1119 {XCS("f"), 4, 6, STRUCT_START_TAG}, {XCS("f"), 8, 6, STRUCT_END_TAG},
1120 {XCS("d"), 2, 7, STRUCT_END_TAG}, {XCS("a"), 0, 8, STRUCT_END_TAG}};
1121 const int expected_count = sizeof(expected) / sizeof(StructDataEntry);
1122 StructData storage;
1123
1124 StructData_Init(&storage);
1125 XML_SetUserData(g_parser, &storage);
1126 XML_SetStartElementHandler(g_parser, start_element_event_handler2);
1127 XML_SetEndElementHandler(g_parser, end_element_event_handler2);
1128 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1129 == XML_STATUS_ERROR)
1130 xml_failure(g_parser);
1131
1132 StructData_CheckItems(&storage, expected, expected_count);
1133 StructData_Dispose(&storage);
1134 }
1135 END_TEST
1136
1137 /* Regression test #4 for SF bug #653180. */
START_TEST(test_line_number_after_error)1138 START_TEST(test_line_number_after_error) {
1139 const char *text = "<a>\n"
1140 " <b>\n"
1141 " </a>"; /* missing </b> */
1142 XML_Size lineno;
1143 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
1144 != XML_STATUS_ERROR)
1145 fail("Expected a parse error");
1146
1147 lineno = XML_GetCurrentLineNumber(g_parser);
1148 if (lineno != 3) {
1149 char buffer[100];
1150 sprintf(buffer, "expected 3 lines, saw %" XML_FMT_INT_MOD "u", lineno);
1151 fail(buffer);
1152 }
1153 }
1154 END_TEST
1155
1156 /* Regression test #5 for SF bug #653180. */
START_TEST(test_column_number_after_error)1157 START_TEST(test_column_number_after_error) {
1158 const char *text = "<a>\n"
1159 " <b>\n"
1160 " </a>"; /* missing </b> */
1161 XML_Size colno;
1162 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
1163 != XML_STATUS_ERROR)
1164 fail("Expected a parse error");
1165
1166 colno = XML_GetCurrentColumnNumber(g_parser);
1167 if (colno != 4) {
1168 char buffer[100];
1169 sprintf(buffer, "expected 4 columns, saw %" XML_FMT_INT_MOD "u", colno);
1170 fail(buffer);
1171 }
1172 }
1173 END_TEST
1174
1175 /* Regression test for SF bug #478332. */
START_TEST(test_really_long_lines)1176 START_TEST(test_really_long_lines) {
1177 /* This parses an input line longer than INIT_DATA_BUF_SIZE
1178 characters long (defined to be 1024 in xmlparse.c). We take a
1179 really cheesy approach to building the input buffer, because
1180 this avoids writing bugs in buffer-filling code.
1181 */
1182 const char *text
1183 = "<e>"
1184 /* 64 chars */
1185 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1186 /* until we have at least 1024 characters on the line: */
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 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1203 "</e>";
1204 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1205 == XML_STATUS_ERROR)
1206 xml_failure(g_parser);
1207 }
1208 END_TEST
1209
1210 /* Test cdata processing across a buffer boundary */
START_TEST(test_really_long_encoded_lines)1211 START_TEST(test_really_long_encoded_lines) {
1212 /* As above, except that we want to provoke an output buffer
1213 * overflow with a non-trivial encoding. For this we need to pass
1214 * the whole cdata in one go, not byte-by-byte.
1215 */
1216 void *buffer;
1217 const char *text
1218 = "<?xml version='1.0' encoding='iso-8859-1'?>"
1219 "<e>"
1220 /* 64 chars */
1221 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1222 /* until we have at least 1024 characters on the line: */
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 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1239 "</e>";
1240 int parse_len = (int)strlen(text);
1241
1242 /* Need a cdata handler to provoke the code path we want to test */
1243 XML_SetCharacterDataHandler(g_parser, dummy_cdata_handler);
1244 buffer = XML_GetBuffer(g_parser, parse_len);
1245 if (buffer == NULL)
1246 fail("Could not allocate parse buffer");
1247 assert(buffer != NULL);
1248 memcpy(buffer, text, parse_len);
1249 if (XML_ParseBuffer(g_parser, parse_len, XML_TRUE) == XML_STATUS_ERROR)
1250 xml_failure(g_parser);
1251 }
1252 END_TEST
1253
1254 /*
1255 * Element event tests.
1256 */
1257
1258 static void XMLCALL
start_element_event_handler(void * userData,const XML_Char * name,const XML_Char ** atts)1259 start_element_event_handler(void *userData, const XML_Char *name,
1260 const XML_Char **atts) {
1261 UNUSED_P(atts);
1262 CharData_AppendXMLChars((CharData *)userData, name, -1);
1263 }
1264
1265 static void XMLCALL
end_element_event_handler(void * userData,const XML_Char * name)1266 end_element_event_handler(void *userData, const XML_Char *name) {
1267 CharData *storage = (CharData *)userData;
1268 CharData_AppendXMLChars(storage, XCS("/"), 1);
1269 CharData_AppendXMLChars(storage, name, -1);
1270 }
1271
START_TEST(test_end_element_events)1272 START_TEST(test_end_element_events) {
1273 const char *text = "<a><b><c/></b><d><f/></d></a>";
1274 const XML_Char *expected = XCS("/c/b/f/d/a");
1275 CharData storage;
1276
1277 CharData_Init(&storage);
1278 XML_SetUserData(g_parser, &storage);
1279 XML_SetEndElementHandler(g_parser, end_element_event_handler);
1280 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1281 == XML_STATUS_ERROR)
1282 xml_failure(g_parser);
1283 CharData_CheckXMLChars(&storage, expected);
1284 }
1285 END_TEST
1286
1287 /*
1288 * Attribute tests.
1289 */
1290
1291 /* Helpers used by the following test; this checks any "attr" and "refs"
1292 attributes to make sure whitespace has been normalized.
1293
1294 Return true if whitespace has been normalized in a string, using
1295 the rules for attribute value normalization. The 'is_cdata' flag
1296 is needed since CDATA attributes don't need to have multiple
1297 whitespace characters collapsed to a single space, while other
1298 attribute data types do. (Section 3.3.3 of the recommendation.)
1299 */
1300 static int
is_whitespace_normalized(const XML_Char * s,int is_cdata)1301 is_whitespace_normalized(const XML_Char *s, int is_cdata) {
1302 int blanks = 0;
1303 int at_start = 1;
1304 while (*s) {
1305 if (*s == XCS(' '))
1306 ++blanks;
1307 else if (*s == XCS('\t') || *s == XCS('\n') || *s == XCS('\r'))
1308 return 0;
1309 else {
1310 if (at_start) {
1311 at_start = 0;
1312 if (blanks && ! is_cdata)
1313 /* illegal leading blanks */
1314 return 0;
1315 } else if (blanks > 1 && ! is_cdata)
1316 return 0;
1317 blanks = 0;
1318 }
1319 ++s;
1320 }
1321 if (blanks && ! is_cdata)
1322 return 0;
1323 return 1;
1324 }
1325
1326 /* Check the attribute whitespace checker: */
1327 static void
testhelper_is_whitespace_normalized(void)1328 testhelper_is_whitespace_normalized(void) {
1329 assert(is_whitespace_normalized(XCS("abc"), 0));
1330 assert(is_whitespace_normalized(XCS("abc"), 1));
1331 assert(is_whitespace_normalized(XCS("abc def ghi"), 0));
1332 assert(is_whitespace_normalized(XCS("abc def ghi"), 1));
1333 assert(! is_whitespace_normalized(XCS(" abc def ghi"), 0));
1334 assert(is_whitespace_normalized(XCS(" abc def ghi"), 1));
1335 assert(! is_whitespace_normalized(XCS("abc def ghi"), 0));
1336 assert(is_whitespace_normalized(XCS("abc def ghi"), 1));
1337 assert(! is_whitespace_normalized(XCS("abc def ghi "), 0));
1338 assert(is_whitespace_normalized(XCS("abc def ghi "), 1));
1339 assert(! is_whitespace_normalized(XCS(" "), 0));
1340 assert(is_whitespace_normalized(XCS(" "), 1));
1341 assert(! is_whitespace_normalized(XCS("\t"), 0));
1342 assert(! is_whitespace_normalized(XCS("\t"), 1));
1343 assert(! is_whitespace_normalized(XCS("\n"), 0));
1344 assert(! is_whitespace_normalized(XCS("\n"), 1));
1345 assert(! is_whitespace_normalized(XCS("\r"), 0));
1346 assert(! is_whitespace_normalized(XCS("\r"), 1));
1347 assert(! is_whitespace_normalized(XCS("abc\t def"), 1));
1348 }
1349
1350 static void XMLCALL
check_attr_contains_normalized_whitespace(void * userData,const XML_Char * name,const XML_Char ** atts)1351 check_attr_contains_normalized_whitespace(void *userData, const XML_Char *name,
1352 const XML_Char **atts) {
1353 int i;
1354 UNUSED_P(userData);
1355 UNUSED_P(name);
1356 for (i = 0; atts[i] != NULL; i += 2) {
1357 const XML_Char *attrname = atts[i];
1358 const XML_Char *value = atts[i + 1];
1359 if (xcstrcmp(XCS("attr"), attrname) == 0
1360 || xcstrcmp(XCS("ents"), attrname) == 0
1361 || xcstrcmp(XCS("refs"), attrname) == 0) {
1362 if (! is_whitespace_normalized(value, 0)) {
1363 char buffer[256];
1364 sprintf(buffer,
1365 "attribute value not normalized: %" XML_FMT_STR
1366 "='%" XML_FMT_STR "'",
1367 attrname, value);
1368 fail(buffer);
1369 }
1370 }
1371 }
1372 }
1373
START_TEST(test_attr_whitespace_normalization)1374 START_TEST(test_attr_whitespace_normalization) {
1375 const char *text
1376 = "<!DOCTYPE doc [\n"
1377 " <!ATTLIST doc\n"
1378 " attr NMTOKENS #REQUIRED\n"
1379 " ents ENTITIES #REQUIRED\n"
1380 " refs IDREFS #REQUIRED>\n"
1381 "]>\n"
1382 "<doc attr=' a b c\t\td\te\t' refs=' id-1 \t id-2\t\t' \n"
1383 " ents=' ent-1 \t\r\n"
1384 " ent-2 ' >\n"
1385 " <e id='id-1'/>\n"
1386 " <e id='id-2'/>\n"
1387 "</doc>";
1388
1389 XML_SetStartElementHandler(g_parser,
1390 check_attr_contains_normalized_whitespace);
1391 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1392 == XML_STATUS_ERROR)
1393 xml_failure(g_parser);
1394 }
1395 END_TEST
1396
1397 /*
1398 * XML declaration tests.
1399 */
1400
START_TEST(test_xmldecl_misplaced)1401 START_TEST(test_xmldecl_misplaced) {
1402 expect_failure("\n"
1403 "<?xml version='1.0'?>\n"
1404 "<a/>",
1405 XML_ERROR_MISPLACED_XML_PI,
1406 "failed to report misplaced XML declaration");
1407 }
1408 END_TEST
1409
START_TEST(test_xmldecl_invalid)1410 START_TEST(test_xmldecl_invalid) {
1411 expect_failure("<?xml version='1.0' \xc3\xa7?>\n<doc/>", XML_ERROR_XML_DECL,
1412 "Failed to report invalid XML declaration");
1413 }
1414 END_TEST
1415
START_TEST(test_xmldecl_missing_attr)1416 START_TEST(test_xmldecl_missing_attr) {
1417 expect_failure("<?xml ='1.0'?>\n<doc/>\n", XML_ERROR_XML_DECL,
1418 "Failed to report missing XML declaration attribute");
1419 }
1420 END_TEST
1421
START_TEST(test_xmldecl_missing_value)1422 START_TEST(test_xmldecl_missing_value) {
1423 expect_failure("<?xml version='1.0' encoding='us-ascii' standalone?>\n"
1424 "<doc/>",
1425 XML_ERROR_XML_DECL,
1426 "Failed to report missing attribute value");
1427 }
1428 END_TEST
1429
1430 /* Regression test for SF bug #584832. */
1431 static int XMLCALL
UnknownEncodingHandler(void * data,const XML_Char * encoding,XML_Encoding * info)1432 UnknownEncodingHandler(void *data, const XML_Char *encoding,
1433 XML_Encoding *info) {
1434 UNUSED_P(data);
1435 if (xcstrcmp(encoding, XCS("unsupported-encoding")) == 0) {
1436 int i;
1437 for (i = 0; i < 256; ++i)
1438 info->map[i] = i;
1439 info->data = NULL;
1440 info->convert = NULL;
1441 info->release = NULL;
1442 return XML_STATUS_OK;
1443 }
1444 return XML_STATUS_ERROR;
1445 }
1446
START_TEST(test_unknown_encoding_internal_entity)1447 START_TEST(test_unknown_encoding_internal_entity) {
1448 const char *text = "<?xml version='1.0' encoding='unsupported-encoding'?>\n"
1449 "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n"
1450 "<test a='&foo;'/>";
1451
1452 XML_SetUnknownEncodingHandler(g_parser, UnknownEncodingHandler, NULL);
1453 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1454 == XML_STATUS_ERROR)
1455 xml_failure(g_parser);
1456 }
1457 END_TEST
1458
1459 /* Test unrecognised encoding handler */
1460 static void
dummy_release(void * data)1461 dummy_release(void *data) {
1462 UNUSED_P(data);
1463 }
1464
1465 static int XMLCALL
UnrecognisedEncodingHandler(void * data,const XML_Char * encoding,XML_Encoding * info)1466 UnrecognisedEncodingHandler(void *data, const XML_Char *encoding,
1467 XML_Encoding *info) {
1468 UNUSED_P(data);
1469 UNUSED_P(encoding);
1470 info->data = NULL;
1471 info->convert = NULL;
1472 info->release = dummy_release;
1473 return XML_STATUS_ERROR;
1474 }
1475
START_TEST(test_unrecognised_encoding_internal_entity)1476 START_TEST(test_unrecognised_encoding_internal_entity) {
1477 const char *text = "<?xml version='1.0' encoding='unsupported-encoding'?>\n"
1478 "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n"
1479 "<test a='&foo;'/>";
1480
1481 XML_SetUnknownEncodingHandler(g_parser, UnrecognisedEncodingHandler, NULL);
1482 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1483 != XML_STATUS_ERROR)
1484 fail("Unrecognised encoding not rejected");
1485 }
1486 END_TEST
1487
1488 /* Regression test for SF bug #620106. */
1489 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)1490 external_entity_loader(XML_Parser parser, const XML_Char *context,
1491 const XML_Char *base, const XML_Char *systemId,
1492 const XML_Char *publicId) {
1493 ExtTest *test_data = (ExtTest *)XML_GetUserData(parser);
1494 XML_Parser extparser;
1495
1496 UNUSED_P(base);
1497 UNUSED_P(systemId);
1498 UNUSED_P(publicId);
1499 extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
1500 if (extparser == NULL)
1501 fail("Could not create external entity parser.");
1502 if (test_data->encoding != NULL) {
1503 if (! XML_SetEncoding(extparser, test_data->encoding))
1504 fail("XML_SetEncoding() ignored for external entity");
1505 }
1506 if (_XML_Parse_SINGLE_BYTES(extparser, test_data->parse_text,
1507 (int)strlen(test_data->parse_text), XML_TRUE)
1508 == XML_STATUS_ERROR) {
1509 xml_failure(extparser);
1510 return XML_STATUS_ERROR;
1511 }
1512 XML_ParserFree(extparser);
1513 return XML_STATUS_OK;
1514 }
1515
START_TEST(test_ext_entity_set_encoding)1516 START_TEST(test_ext_entity_set_encoding) {
1517 const char *text = "<!DOCTYPE doc [\n"
1518 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1519 "]>\n"
1520 "<doc>&en;</doc>";
1521 ExtTest test_data
1522 = {/* This text says it's an unsupported encoding, but it's really
1523 UTF-8, which we tell Expat using XML_SetEncoding().
1524 */
1525 "<?xml encoding='iso-8859-3'?>\xC3\xA9", XCS("utf-8"), NULL};
1526 #ifdef XML_UNICODE
1527 const XML_Char *expected = XCS("\x00e9");
1528 #else
1529 const XML_Char *expected = XCS("\xc3\xa9");
1530 #endif
1531
1532 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1533 run_ext_character_check(text, &test_data, expected);
1534 }
1535 END_TEST
1536
1537 /* Test external entities with no handler */
START_TEST(test_ext_entity_no_handler)1538 START_TEST(test_ext_entity_no_handler) {
1539 const char *text = "<!DOCTYPE doc [\n"
1540 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1541 "]>\n"
1542 "<doc>&en;</doc>";
1543
1544 XML_SetDefaultHandler(g_parser, dummy_default_handler);
1545 run_character_check(text, XCS(""));
1546 }
1547 END_TEST
1548
1549 /* Test UTF-8 BOM is accepted */
START_TEST(test_ext_entity_set_bom)1550 START_TEST(test_ext_entity_set_bom) {
1551 const char *text = "<!DOCTYPE doc [\n"
1552 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1553 "]>\n"
1554 "<doc>&en;</doc>";
1555 ExtTest test_data = {"\xEF\xBB\xBF" /* BOM */
1556 "<?xml encoding='iso-8859-3'?>"
1557 "\xC3\xA9",
1558 XCS("utf-8"), NULL};
1559 #ifdef XML_UNICODE
1560 const XML_Char *expected = XCS("\x00e9");
1561 #else
1562 const XML_Char *expected = XCS("\xc3\xa9");
1563 #endif
1564
1565 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1566 run_ext_character_check(text, &test_data, expected);
1567 }
1568 END_TEST
1569
1570 /* Test that bad encodings are faulted */
1571 typedef struct ext_faults {
1572 const char *parse_text;
1573 const char *fail_text;
1574 const XML_Char *encoding;
1575 enum XML_Error error;
1576 } ExtFaults;
1577
1578 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)1579 external_entity_faulter(XML_Parser parser, const XML_Char *context,
1580 const XML_Char *base, const XML_Char *systemId,
1581 const XML_Char *publicId) {
1582 XML_Parser ext_parser;
1583 ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser);
1584
1585 UNUSED_P(base);
1586 UNUSED_P(systemId);
1587 UNUSED_P(publicId);
1588 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
1589 if (ext_parser == NULL)
1590 fail("Could not create external entity parser");
1591 if (fault->encoding != NULL) {
1592 if (! XML_SetEncoding(ext_parser, fault->encoding))
1593 fail("XML_SetEncoding failed");
1594 }
1595 if (_XML_Parse_SINGLE_BYTES(ext_parser, fault->parse_text,
1596 (int)strlen(fault->parse_text), XML_TRUE)
1597 != XML_STATUS_ERROR)
1598 fail(fault->fail_text);
1599 if (XML_GetErrorCode(ext_parser) != fault->error)
1600 xml_failure(ext_parser);
1601
1602 XML_ParserFree(ext_parser);
1603 return XML_STATUS_ERROR;
1604 }
1605
START_TEST(test_ext_entity_bad_encoding)1606 START_TEST(test_ext_entity_bad_encoding) {
1607 const char *text = "<!DOCTYPE doc [\n"
1608 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1609 "]>\n"
1610 "<doc>&en;</doc>";
1611 ExtFaults fault
1612 = {"<?xml encoding='iso-8859-3'?>u", "Unsupported encoding not faulted",
1613 XCS("unknown"), XML_ERROR_UNKNOWN_ENCODING};
1614
1615 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
1616 XML_SetUserData(g_parser, &fault);
1617 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
1618 "Bad encoding should not have been accepted");
1619 }
1620 END_TEST
1621
1622 /* Try handing an invalid encoding to an external entity parser */
START_TEST(test_ext_entity_bad_encoding_2)1623 START_TEST(test_ext_entity_bad_encoding_2) {
1624 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
1625 "<!DOCTYPE doc SYSTEM 'foo'>\n"
1626 "<doc>&entity;</doc>";
1627 ExtFaults fault
1628 = {"<!ELEMENT doc (#PCDATA)*>", "Unknown encoding not faulted",
1629 XCS("unknown-encoding"), XML_ERROR_UNKNOWN_ENCODING};
1630
1631 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1632 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
1633 XML_SetUserData(g_parser, &fault);
1634 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
1635 "Bad encoding not faulted in external entity handler");
1636 }
1637 END_TEST
1638
1639 /* Test that no error is reported for unknown entities if we don't
1640 read an external subset. This was fixed in Expat 1.95.5.
1641 */
START_TEST(test_wfc_undeclared_entity_unread_external_subset)1642 START_TEST(test_wfc_undeclared_entity_unread_external_subset) {
1643 const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
1644 "<doc>&entity;</doc>";
1645
1646 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1647 == XML_STATUS_ERROR)
1648 xml_failure(g_parser);
1649 }
1650 END_TEST
1651
1652 /* Test that an error is reported for unknown entities if we don't
1653 have an external subset.
1654 */
START_TEST(test_wfc_undeclared_entity_no_external_subset)1655 START_TEST(test_wfc_undeclared_entity_no_external_subset) {
1656 expect_failure("<doc>&entity;</doc>", XML_ERROR_UNDEFINED_ENTITY,
1657 "Parser did not report undefined entity w/out a DTD.");
1658 }
1659 END_TEST
1660
1661 /* Test that an error is reported for unknown entities if we don't
1662 read an external subset, but have been declared standalone.
1663 */
START_TEST(test_wfc_undeclared_entity_standalone)1664 START_TEST(test_wfc_undeclared_entity_standalone) {
1665 const char *text
1666 = "<?xml version='1.0' encoding='us-ascii' standalone='yes'?>\n"
1667 "<!DOCTYPE doc SYSTEM 'foo'>\n"
1668 "<doc>&entity;</doc>";
1669
1670 expect_failure(text, XML_ERROR_UNDEFINED_ENTITY,
1671 "Parser did not report undefined entity (standalone).");
1672 }
1673 END_TEST
1674
1675 /* Test that an error is reported for unknown entities if we have read
1676 an external subset, and standalone is true.
1677 */
START_TEST(test_wfc_undeclared_entity_with_external_subset_standalone)1678 START_TEST(test_wfc_undeclared_entity_with_external_subset_standalone) {
1679 const char *text
1680 = "<?xml version='1.0' encoding='us-ascii' standalone='yes'?>\n"
1681 "<!DOCTYPE doc SYSTEM 'foo'>\n"
1682 "<doc>&entity;</doc>";
1683 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
1684
1685 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1686 XML_SetUserData(g_parser, &test_data);
1687 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1688 expect_failure(text, XML_ERROR_UNDEFINED_ENTITY,
1689 "Parser did not report undefined entity (external DTD).");
1690 }
1691 END_TEST
1692
1693 /* Test that external entity handling is not done if the parsing flag
1694 * is set to UNLESS_STANDALONE
1695 */
START_TEST(test_entity_with_external_subset_unless_standalone)1696 START_TEST(test_entity_with_external_subset_unless_standalone) {
1697 const char *text
1698 = "<?xml version='1.0' encoding='us-ascii' standalone='yes'?>\n"
1699 "<!DOCTYPE doc SYSTEM 'foo'>\n"
1700 "<doc>&entity;</doc>";
1701 ExtTest test_data = {"<!ENTITY entity 'bar'>", NULL, NULL};
1702
1703 XML_SetParamEntityParsing(g_parser,
1704 XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE);
1705 XML_SetUserData(g_parser, &test_data);
1706 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1707 expect_failure(text, XML_ERROR_UNDEFINED_ENTITY,
1708 "Parser did not report undefined entity");
1709 }
1710 END_TEST
1711
1712 /* Test that no error is reported for unknown entities if we have read
1713 an external subset, and standalone is false.
1714 */
START_TEST(test_wfc_undeclared_entity_with_external_subset)1715 START_TEST(test_wfc_undeclared_entity_with_external_subset) {
1716 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
1717 "<!DOCTYPE doc SYSTEM 'foo'>\n"
1718 "<doc>&entity;</doc>";
1719 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
1720
1721 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1722 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1723 run_ext_character_check(text, &test_data, XCS(""));
1724 }
1725 END_TEST
1726
1727 /* Test that an error is reported if our NotStandalone handler fails */
1728 static int XMLCALL
reject_not_standalone_handler(void * userData)1729 reject_not_standalone_handler(void *userData) {
1730 UNUSED_P(userData);
1731 return XML_STATUS_ERROR;
1732 }
1733
START_TEST(test_not_standalone_handler_reject)1734 START_TEST(test_not_standalone_handler_reject) {
1735 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
1736 "<!DOCTYPE doc SYSTEM 'foo'>\n"
1737 "<doc>&entity;</doc>";
1738 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
1739
1740 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1741 XML_SetUserData(g_parser, &test_data);
1742 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1743 XML_SetNotStandaloneHandler(g_parser, reject_not_standalone_handler);
1744 expect_failure(text, XML_ERROR_NOT_STANDALONE,
1745 "NotStandalone handler failed to reject");
1746
1747 /* Try again but without external entity handling */
1748 XML_ParserReset(g_parser, NULL);
1749 XML_SetNotStandaloneHandler(g_parser, reject_not_standalone_handler);
1750 expect_failure(text, XML_ERROR_NOT_STANDALONE,
1751 "NotStandalone handler failed to reject");
1752 }
1753 END_TEST
1754
1755 /* Test that no error is reported if our NotStandalone handler succeeds */
1756 static int XMLCALL
accept_not_standalone_handler(void * userData)1757 accept_not_standalone_handler(void *userData) {
1758 UNUSED_P(userData);
1759 return XML_STATUS_OK;
1760 }
1761
START_TEST(test_not_standalone_handler_accept)1762 START_TEST(test_not_standalone_handler_accept) {
1763 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
1764 "<!DOCTYPE doc SYSTEM 'foo'>\n"
1765 "<doc>&entity;</doc>";
1766 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
1767
1768 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1769 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1770 XML_SetNotStandaloneHandler(g_parser, accept_not_standalone_handler);
1771 run_ext_character_check(text, &test_data, XCS(""));
1772
1773 /* Repeat without the external entity handler */
1774 XML_ParserReset(g_parser, NULL);
1775 XML_SetNotStandaloneHandler(g_parser, accept_not_standalone_handler);
1776 run_character_check(text, XCS(""));
1777 }
1778 END_TEST
1779
START_TEST(test_wfc_no_recursive_entity_refs)1780 START_TEST(test_wfc_no_recursive_entity_refs) {
1781 const char *text = "<!DOCTYPE doc [\n"
1782 " <!ENTITY entity '&entity;'>\n"
1783 "]>\n"
1784 "<doc>&entity;</doc>";
1785
1786 expect_failure(text, XML_ERROR_RECURSIVE_ENTITY_REF,
1787 "Parser did not report recursive entity reference.");
1788 }
1789 END_TEST
1790
1791 /* Test incomplete external entities are faulted */
START_TEST(test_ext_entity_invalid_parse)1792 START_TEST(test_ext_entity_invalid_parse) {
1793 const char *text = "<!DOCTYPE doc [\n"
1794 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1795 "]>\n"
1796 "<doc>&en;</doc>";
1797 const ExtFaults faults[]
1798 = {{"<", "Incomplete element declaration not faulted", NULL,
1799 XML_ERROR_UNCLOSED_TOKEN},
1800 {"<\xe2\x82", /* First two bytes of a three-byte char */
1801 "Incomplete character not faulted", NULL, XML_ERROR_PARTIAL_CHAR},
1802 {"<tag>\xe2\x82", "Incomplete character in CDATA not faulted", NULL,
1803 XML_ERROR_PARTIAL_CHAR},
1804 {NULL, NULL, NULL, XML_ERROR_NONE}};
1805 const ExtFaults *fault = faults;
1806
1807 for (; fault->parse_text != NULL; fault++) {
1808 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1809 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
1810 XML_SetUserData(g_parser, (void *)fault);
1811 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
1812 "Parser did not report external entity error");
1813 XML_ParserReset(g_parser, NULL);
1814 }
1815 }
1816 END_TEST
1817
1818 /* Regression test for SF bug #483514. */
START_TEST(test_dtd_default_handling)1819 START_TEST(test_dtd_default_handling) {
1820 const char *text = "<!DOCTYPE doc [\n"
1821 "<!ENTITY e SYSTEM 'http://example.org/e'>\n"
1822 "<!NOTATION n SYSTEM 'http://example.org/n'>\n"
1823 "<!ELEMENT doc EMPTY>\n"
1824 "<!ATTLIST doc a CDATA #IMPLIED>\n"
1825 "<?pi in dtd?>\n"
1826 "<!--comment in dtd-->\n"
1827 "]><doc/>";
1828
1829 XML_SetDefaultHandler(g_parser, accumulate_characters);
1830 XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler);
1831 XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler);
1832 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
1833 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
1834 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
1835 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
1836 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
1837 XML_SetCommentHandler(g_parser, dummy_comment_handler);
1838 XML_SetStartCdataSectionHandler(g_parser, dummy_start_cdata_handler);
1839 XML_SetEndCdataSectionHandler(g_parser, dummy_end_cdata_handler);
1840 run_character_check(text, XCS("\n\n\n\n\n\n\n<doc/>"));
1841 }
1842 END_TEST
1843
1844 /* Test handling of attribute declarations */
1845 typedef struct AttTest {
1846 const char *definition;
1847 const XML_Char *element_name;
1848 const XML_Char *attr_name;
1849 const XML_Char *attr_type;
1850 const XML_Char *default_value;
1851 int is_required;
1852 } AttTest;
1853
1854 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)1855 verify_attlist_decl_handler(void *userData, const XML_Char *element_name,
1856 const XML_Char *attr_name,
1857 const XML_Char *attr_type,
1858 const XML_Char *default_value, int is_required) {
1859 AttTest *at = (AttTest *)userData;
1860
1861 if (xcstrcmp(element_name, at->element_name))
1862 fail("Unexpected element name in attribute declaration");
1863 if (xcstrcmp(attr_name, at->attr_name))
1864 fail("Unexpected attribute name in attribute declaration");
1865 if (xcstrcmp(attr_type, at->attr_type))
1866 fail("Unexpected attribute type in attribute declaration");
1867 if ((default_value == NULL && at->default_value != NULL)
1868 || (default_value != NULL && at->default_value == NULL)
1869 || (default_value != NULL && xcstrcmp(default_value, at->default_value)))
1870 fail("Unexpected default value in attribute declaration");
1871 if (is_required != at->is_required)
1872 fail("Requirement mismatch in attribute declaration");
1873 }
1874
START_TEST(test_dtd_attr_handling)1875 START_TEST(test_dtd_attr_handling) {
1876 const char *prolog = "<!DOCTYPE doc [\n"
1877 "<!ELEMENT doc EMPTY>\n";
1878 AttTest attr_data[]
1879 = {{"<!ATTLIST doc a ( one | two | three ) #REQUIRED>\n"
1880 "]>"
1881 "<doc a='two'/>",
1882 XCS("doc"), XCS("a"),
1883 XCS("(one|two|three)"), /* Extraneous spaces will be removed */
1884 NULL, XML_TRUE},
1885 {"<!NOTATION foo SYSTEM 'http://example.org/foo'>\n"
1886 "<!ATTLIST doc a NOTATION (foo) #IMPLIED>\n"
1887 "]>"
1888 "<doc/>",
1889 XCS("doc"), XCS("a"), XCS("NOTATION(foo)"), NULL, XML_FALSE},
1890 {"<!ATTLIST doc a NOTATION (foo) 'bar'>\n"
1891 "]>"
1892 "<doc/>",
1893 XCS("doc"), XCS("a"), XCS("NOTATION(foo)"), XCS("bar"), XML_FALSE},
1894 {"<!ATTLIST doc a CDATA '\xdb\xb2'>\n"
1895 "]>"
1896 "<doc/>",
1897 XCS("doc"), XCS("a"), XCS("CDATA"),
1898 #ifdef XML_UNICODE
1899 XCS("\x06f2"),
1900 #else
1901 XCS("\xdb\xb2"),
1902 #endif
1903 XML_FALSE},
1904 {NULL, NULL, NULL, NULL, NULL, XML_FALSE}};
1905 AttTest *test;
1906
1907 for (test = attr_data; test->definition != NULL; test++) {
1908 XML_SetAttlistDeclHandler(g_parser, verify_attlist_decl_handler);
1909 XML_SetUserData(g_parser, test);
1910 if (_XML_Parse_SINGLE_BYTES(g_parser, prolog, (int)strlen(prolog),
1911 XML_FALSE)
1912 == XML_STATUS_ERROR)
1913 xml_failure(g_parser);
1914 if (_XML_Parse_SINGLE_BYTES(g_parser, test->definition,
1915 (int)strlen(test->definition), XML_TRUE)
1916 == XML_STATUS_ERROR)
1917 xml_failure(g_parser);
1918 XML_ParserReset(g_parser, NULL);
1919 }
1920 }
1921 END_TEST
1922
1923 /* See related SF bug #673791.
1924 When namespace processing is enabled, setting the namespace URI for
1925 a prefix is not allowed; this test ensures that it *is* allowed
1926 when namespace processing is not enabled.
1927 (See Namespaces in XML, section 2.)
1928 */
START_TEST(test_empty_ns_without_namespaces)1929 START_TEST(test_empty_ns_without_namespaces) {
1930 const char *text = "<doc xmlns:prefix='http://example.org/'>\n"
1931 " <e xmlns:prefix=''/>\n"
1932 "</doc>";
1933
1934 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1935 == XML_STATUS_ERROR)
1936 xml_failure(g_parser);
1937 }
1938 END_TEST
1939
1940 /* Regression test for SF bug #824420.
1941 Checks that an xmlns:prefix attribute set in an attribute's default
1942 value isn't misinterpreted.
1943 */
START_TEST(test_ns_in_attribute_default_without_namespaces)1944 START_TEST(test_ns_in_attribute_default_without_namespaces) {
1945 const char *text = "<!DOCTYPE e:element [\n"
1946 " <!ATTLIST e:element\n"
1947 " xmlns:e CDATA 'http://example.org/'>\n"
1948 " ]>\n"
1949 "<e:element/>";
1950
1951 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1952 == XML_STATUS_ERROR)
1953 xml_failure(g_parser);
1954 }
1955 END_TEST
1956
1957 static const char *long_character_data_text
1958 = "<?xml version='1.0' encoding='iso-8859-1'?><s>"
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 "012345678901234567890123456789012345678901234567890123456789"
1979 "</s>";
1980
1981 static XML_Bool resumable = XML_FALSE;
1982
1983 static void
clearing_aborting_character_handler(void * userData,const XML_Char * s,int len)1984 clearing_aborting_character_handler(void *userData, const XML_Char *s,
1985 int len) {
1986 UNUSED_P(userData);
1987 UNUSED_P(s);
1988 UNUSED_P(len);
1989 XML_StopParser(g_parser, resumable);
1990 XML_SetCharacterDataHandler(g_parser, NULL);
1991 }
1992
1993 /* Regression test for SF bug #1515266: missing check of stopped
1994 parser in doContext() 'for' loop. */
START_TEST(test_stop_parser_between_char_data_calls)1995 START_TEST(test_stop_parser_between_char_data_calls) {
1996 /* The sample data must be big enough that there are two calls to
1997 the character data handler from within the inner "for" loop of
1998 the XML_TOK_DATA_CHARS case in doContent(), and the character
1999 handler must stop the parser and clear the character data
2000 handler.
2001 */
2002 const char *text = long_character_data_text;
2003
2004 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2005 resumable = XML_FALSE;
2006 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2007 != XML_STATUS_ERROR)
2008 xml_failure(g_parser);
2009 if (XML_GetErrorCode(g_parser) != XML_ERROR_ABORTED)
2010 xml_failure(g_parser);
2011 }
2012 END_TEST
2013
2014 /* Regression test for SF bug #1515266: missing check of stopped
2015 parser in doContext() 'for' loop. */
START_TEST(test_suspend_parser_between_char_data_calls)2016 START_TEST(test_suspend_parser_between_char_data_calls) {
2017 /* The sample data must be big enough that there are two calls to
2018 the character data handler from within the inner "for" loop of
2019 the XML_TOK_DATA_CHARS case in doContent(), and the character
2020 handler must stop the parser and clear the character data
2021 handler.
2022 */
2023 const char *text = long_character_data_text;
2024
2025 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2026 resumable = XML_TRUE;
2027 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2028 != XML_STATUS_SUSPENDED)
2029 xml_failure(g_parser);
2030 if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE)
2031 xml_failure(g_parser);
2032 /* Try parsing directly */
2033 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
2034 != XML_STATUS_ERROR)
2035 fail("Attempt to continue parse while suspended not faulted");
2036 if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED)
2037 fail("Suspended parse not faulted with correct error");
2038 }
2039 END_TEST
2040
2041 static XML_Bool abortable = XML_FALSE;
2042
2043 static void
parser_stop_character_handler(void * userData,const XML_Char * s,int len)2044 parser_stop_character_handler(void *userData, const XML_Char *s, int len) {
2045 UNUSED_P(userData);
2046 UNUSED_P(s);
2047 UNUSED_P(len);
2048 XML_StopParser(g_parser, resumable);
2049 XML_SetCharacterDataHandler(g_parser, NULL);
2050 if (! resumable) {
2051 /* Check that aborting an aborted parser is faulted */
2052 if (XML_StopParser(g_parser, XML_FALSE) != XML_STATUS_ERROR)
2053 fail("Aborting aborted parser not faulted");
2054 if (XML_GetErrorCode(g_parser) != XML_ERROR_FINISHED)
2055 xml_failure(g_parser);
2056 } else if (abortable) {
2057 /* Check that aborting a suspended parser works */
2058 if (XML_StopParser(g_parser, XML_FALSE) == XML_STATUS_ERROR)
2059 xml_failure(g_parser);
2060 } else {
2061 /* Check that suspending a suspended parser works */
2062 if (XML_StopParser(g_parser, XML_TRUE) != XML_STATUS_ERROR)
2063 fail("Suspending suspended parser not faulted");
2064 if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED)
2065 xml_failure(g_parser);
2066 }
2067 }
2068
2069 /* Test repeated calls to XML_StopParser are handled correctly */
START_TEST(test_repeated_stop_parser_between_char_data_calls)2070 START_TEST(test_repeated_stop_parser_between_char_data_calls) {
2071 const char *text = long_character_data_text;
2072
2073 XML_SetCharacterDataHandler(g_parser, parser_stop_character_handler);
2074 resumable = XML_FALSE;
2075 abortable = XML_FALSE;
2076 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2077 != XML_STATUS_ERROR)
2078 fail("Failed to double-stop parser");
2079
2080 XML_ParserReset(g_parser, NULL);
2081 XML_SetCharacterDataHandler(g_parser, parser_stop_character_handler);
2082 resumable = XML_TRUE;
2083 abortable = XML_FALSE;
2084 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2085 != XML_STATUS_SUSPENDED)
2086 fail("Failed to double-suspend parser");
2087
2088 XML_ParserReset(g_parser, NULL);
2089 XML_SetCharacterDataHandler(g_parser, parser_stop_character_handler);
2090 resumable = XML_TRUE;
2091 abortable = XML_TRUE;
2092 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2093 != XML_STATUS_ERROR)
2094 fail("Failed to suspend-abort parser");
2095 }
2096 END_TEST
2097
START_TEST(test_good_cdata_ascii)2098 START_TEST(test_good_cdata_ascii) {
2099 const char *text = "<a><![CDATA[<greeting>Hello, world!</greeting>]]></a>";
2100 const XML_Char *expected = XCS("<greeting>Hello, world!</greeting>");
2101
2102 CharData storage;
2103 CharData_Init(&storage);
2104 XML_SetUserData(g_parser, &storage);
2105 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2106 /* Add start and end handlers for coverage */
2107 XML_SetStartCdataSectionHandler(g_parser, dummy_start_cdata_handler);
2108 XML_SetEndCdataSectionHandler(g_parser, dummy_end_cdata_handler);
2109
2110 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2111 == XML_STATUS_ERROR)
2112 xml_failure(g_parser);
2113 CharData_CheckXMLChars(&storage, expected);
2114
2115 /* Try again, this time with a default handler */
2116 XML_ParserReset(g_parser, NULL);
2117 CharData_Init(&storage);
2118 XML_SetUserData(g_parser, &storage);
2119 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2120 XML_SetDefaultHandler(g_parser, dummy_default_handler);
2121
2122 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2123 == XML_STATUS_ERROR)
2124 xml_failure(g_parser);
2125 CharData_CheckXMLChars(&storage, expected);
2126 }
2127 END_TEST
2128
START_TEST(test_good_cdata_utf16)2129 START_TEST(test_good_cdata_utf16) {
2130 /* Test data is:
2131 * <?xml version='1.0' encoding='utf-16'?>
2132 * <a><![CDATA[hello]]></a>
2133 */
2134 const char text[]
2135 = "\0<\0?\0x\0m\0l\0"
2136 " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2137 " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0"
2138 "1\0"
2139 "6\0'"
2140 "\0?\0>\0\n"
2141 "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0[\0h\0e\0l\0l\0o\0]\0]\0>\0<\0/\0a\0>";
2142 const XML_Char *expected = XCS("hello");
2143
2144 CharData storage;
2145 CharData_Init(&storage);
2146 XML_SetUserData(g_parser, &storage);
2147 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2148
2149 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
2150 == XML_STATUS_ERROR)
2151 xml_failure(g_parser);
2152 CharData_CheckXMLChars(&storage, expected);
2153 }
2154 END_TEST
2155
START_TEST(test_good_cdata_utf16_le)2156 START_TEST(test_good_cdata_utf16_le) {
2157 /* Test data is:
2158 * <?xml version='1.0' encoding='utf-16'?>
2159 * <a><![CDATA[hello]]></a>
2160 */
2161 const char text[]
2162 = "<\0?\0x\0m\0l\0"
2163 " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2164 " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0"
2165 "1\0"
2166 "6\0'"
2167 "\0?\0>\0\n"
2168 "\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";
2169 const XML_Char *expected = XCS("hello");
2170
2171 CharData storage;
2172 CharData_Init(&storage);
2173 XML_SetUserData(g_parser, &storage);
2174 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2175
2176 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
2177 == XML_STATUS_ERROR)
2178 xml_failure(g_parser);
2179 CharData_CheckXMLChars(&storage, expected);
2180 }
2181 END_TEST
2182
2183 /* Test UTF16 conversion of a long cdata string */
2184
2185 /* 16 characters: handy macro to reduce visual clutter */
2186 #define A_TO_P_IN_UTF16 "\0A\0B\0C\0D\0E\0F\0G\0H\0I\0J\0K\0L\0M\0N\0O\0P"
2187
START_TEST(test_long_cdata_utf16)2188 START_TEST(test_long_cdata_utf16) {
2189 /* Test data is:
2190 * <?xlm version='1.0' encoding='utf-16'?>
2191 * <a><![CDATA[
2192 * ABCDEFGHIJKLMNOP
2193 * ]]></a>
2194 */
2195 const char text[]
2196 = "\0<\0?\0x\0m\0l\0 "
2197 "\0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0 "
2198 "\0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0\x31\0\x36\0'\0?\0>"
2199 "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0["
2200 /* 64 characters per line */
2201 /* clang-format off */
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 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
2218 A_TO_P_IN_UTF16
2219 /* clang-format on */
2220 "\0]\0]\0>\0<\0/\0a\0>";
2221 const XML_Char *expected =
2222 /* clang-format off */
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("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2239 XCS("ABCDEFGHIJKLMNOP");
2240 /* clang-format on */
2241 CharData storage;
2242 void *buffer;
2243
2244 CharData_Init(&storage);
2245 XML_SetUserData(g_parser, &storage);
2246 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2247 buffer = XML_GetBuffer(g_parser, sizeof(text) - 1);
2248 if (buffer == NULL)
2249 fail("Could not allocate parse buffer");
2250 assert(buffer != NULL);
2251 memcpy(buffer, text, sizeof(text) - 1);
2252 if (XML_ParseBuffer(g_parser, sizeof(text) - 1, XML_TRUE) == XML_STATUS_ERROR)
2253 xml_failure(g_parser);
2254 CharData_CheckXMLChars(&storage, expected);
2255 }
2256 END_TEST
2257
2258 /* Test handling of multiple unit UTF-16 characters */
START_TEST(test_multichar_cdata_utf16)2259 START_TEST(test_multichar_cdata_utf16) {
2260 /* Test data is:
2261 * <?xml version='1.0' encoding='utf-16'?>
2262 * <a><![CDATA[{MINIM}{CROTCHET}]]></a>
2263 *
2264 * where {MINIM} is U+1d15e (a minim or half-note)
2265 * UTF-16: 0xd834 0xdd5e
2266 * UTF-8: 0xf0 0x9d 0x85 0x9e
2267 * and {CROTCHET} is U+1d15f (a crotchet or quarter-note)
2268 * UTF-16: 0xd834 0xdd5f
2269 * UTF-8: 0xf0 0x9d 0x85 0x9f
2270 */
2271 const char text[] = "\0<\0?\0x\0m\0l\0"
2272 " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2273 " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0"
2274 "1\0"
2275 "6\0'"
2276 "\0?\0>\0\n"
2277 "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0["
2278 "\xd8\x34\xdd\x5e\xd8\x34\xdd\x5f"
2279 "\0]\0]\0>\0<\0/\0a\0>";
2280 #ifdef XML_UNICODE
2281 const XML_Char *expected = XCS("\xd834\xdd5e\xd834\xdd5f");
2282 #else
2283 const XML_Char *expected = XCS("\xf0\x9d\x85\x9e\xf0\x9d\x85\x9f");
2284 #endif
2285 CharData storage;
2286
2287 CharData_Init(&storage);
2288 XML_SetUserData(g_parser, &storage);
2289 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2290
2291 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
2292 == XML_STATUS_ERROR)
2293 xml_failure(g_parser);
2294 CharData_CheckXMLChars(&storage, expected);
2295 }
2296 END_TEST
2297
2298 /* Test that an element name with a UTF-16 surrogate pair is rejected */
START_TEST(test_utf16_bad_surrogate_pair)2299 START_TEST(test_utf16_bad_surrogate_pair) {
2300 /* Test data is:
2301 * <?xml version='1.0' encoding='utf-16'?>
2302 * <a><![CDATA[{BADLINB}]]></a>
2303 *
2304 * where {BADLINB} is U+10000 (the first Linear B character)
2305 * with the UTF-16 surrogate pair in the wrong order, i.e.
2306 * 0xdc00 0xd800
2307 */
2308 const char text[] = "\0<\0?\0x\0m\0l\0"
2309 " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2310 " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0"
2311 "1\0"
2312 "6\0'"
2313 "\0?\0>\0\n"
2314 "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0["
2315 "\xdc\x00\xd8\x00"
2316 "\0]\0]\0>\0<\0/\0a\0>";
2317
2318 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
2319 != XML_STATUS_ERROR)
2320 fail("Reversed UTF-16 surrogate pair not faulted");
2321 if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
2322 xml_failure(g_parser);
2323 }
2324 END_TEST
2325
START_TEST(test_bad_cdata)2326 START_TEST(test_bad_cdata) {
2327 struct CaseData {
2328 const char *text;
2329 enum XML_Error expectedError;
2330 };
2331
2332 struct CaseData cases[]
2333 = {{"<a><", XML_ERROR_UNCLOSED_TOKEN},
2334 {"<a><!", XML_ERROR_UNCLOSED_TOKEN},
2335 {"<a><![", XML_ERROR_UNCLOSED_TOKEN},
2336 {"<a><![C", XML_ERROR_UNCLOSED_TOKEN},
2337 {"<a><![CD", XML_ERROR_UNCLOSED_TOKEN},
2338 {"<a><![CDA", XML_ERROR_UNCLOSED_TOKEN},
2339 {"<a><![CDAT", XML_ERROR_UNCLOSED_TOKEN},
2340 {"<a><![CDATA", XML_ERROR_UNCLOSED_TOKEN},
2341
2342 {"<a><![CDATA[", XML_ERROR_UNCLOSED_CDATA_SECTION},
2343 {"<a><![CDATA[]", XML_ERROR_UNCLOSED_CDATA_SECTION},
2344 {"<a><![CDATA[]]", XML_ERROR_UNCLOSED_CDATA_SECTION},
2345
2346 {"<a><!<a/>", XML_ERROR_INVALID_TOKEN},
2347 {"<a><![<a/>", XML_ERROR_UNCLOSED_TOKEN}, /* ?! */
2348 {"<a><![C<a/>", XML_ERROR_UNCLOSED_TOKEN}, /* ?! */
2349 {"<a><![CD<a/>", XML_ERROR_INVALID_TOKEN},
2350 {"<a><![CDA<a/>", XML_ERROR_INVALID_TOKEN},
2351 {"<a><![CDAT<a/>", XML_ERROR_INVALID_TOKEN},
2352 {"<a><![CDATA<a/>", XML_ERROR_INVALID_TOKEN},
2353
2354 {"<a><![CDATA[<a/>", XML_ERROR_UNCLOSED_CDATA_SECTION},
2355 {"<a><![CDATA[]<a/>", XML_ERROR_UNCLOSED_CDATA_SECTION},
2356 {"<a><![CDATA[]]<a/>", XML_ERROR_UNCLOSED_CDATA_SECTION}};
2357
2358 size_t i = 0;
2359 for (; i < sizeof(cases) / sizeof(struct CaseData); i++) {
2360 const enum XML_Status actualStatus = _XML_Parse_SINGLE_BYTES(
2361 g_parser, cases[i].text, (int)strlen(cases[i].text), XML_TRUE);
2362 const enum XML_Error actualError = XML_GetErrorCode(g_parser);
2363
2364 assert(actualStatus == XML_STATUS_ERROR);
2365
2366 if (actualError != cases[i].expectedError) {
2367 char message[100];
2368 sprintf(message,
2369 "Expected error %d but got error %d for case %u: \"%s\"\n",
2370 cases[i].expectedError, actualError, (unsigned int)i + 1,
2371 cases[i].text);
2372 fail(message);
2373 }
2374
2375 XML_ParserReset(g_parser, NULL);
2376 }
2377 }
2378 END_TEST
2379
2380 /* Test failures in UTF-16 CDATA */
START_TEST(test_bad_cdata_utf16)2381 START_TEST(test_bad_cdata_utf16) {
2382 struct CaseData {
2383 size_t text_bytes;
2384 const char *text;
2385 enum XML_Error expected_error;
2386 };
2387
2388 const char prolog[] = "\0<\0?\0x\0m\0l\0"
2389 " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2390 " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0"
2391 "1\0"
2392 "6\0'"
2393 "\0?\0>\0\n"
2394 "\0<\0a\0>";
2395 struct CaseData cases[] = {
2396 {1, "\0", XML_ERROR_UNCLOSED_TOKEN},
2397 {2, "\0<", XML_ERROR_UNCLOSED_TOKEN},
2398 {3, "\0<\0", XML_ERROR_UNCLOSED_TOKEN},
2399 {4, "\0<\0!", XML_ERROR_UNCLOSED_TOKEN},
2400 {5, "\0<\0!\0", XML_ERROR_UNCLOSED_TOKEN},
2401 {6, "\0<\0!\0[", XML_ERROR_UNCLOSED_TOKEN},
2402 {7, "\0<\0!\0[\0", XML_ERROR_UNCLOSED_TOKEN},
2403 {8, "\0<\0!\0[\0C", XML_ERROR_UNCLOSED_TOKEN},
2404 {9, "\0<\0!\0[\0C\0", XML_ERROR_UNCLOSED_TOKEN},
2405 {10, "\0<\0!\0[\0C\0D", XML_ERROR_UNCLOSED_TOKEN},
2406 {11, "\0<\0!\0[\0C\0D\0", XML_ERROR_UNCLOSED_TOKEN},
2407 {12, "\0<\0!\0[\0C\0D\0A", XML_ERROR_UNCLOSED_TOKEN},
2408 {13, "\0<\0!\0[\0C\0D\0A\0", XML_ERROR_UNCLOSED_TOKEN},
2409 {14, "\0<\0!\0[\0C\0D\0A\0T", XML_ERROR_UNCLOSED_TOKEN},
2410 {15, "\0<\0!\0[\0C\0D\0A\0T\0", XML_ERROR_UNCLOSED_TOKEN},
2411 {16, "\0<\0!\0[\0C\0D\0A\0T\0A", XML_ERROR_UNCLOSED_TOKEN},
2412 {17, "\0<\0!\0[\0C\0D\0A\0T\0A\0", XML_ERROR_UNCLOSED_TOKEN},
2413 {18, "\0<\0!\0[\0C\0D\0A\0T\0A\0[", XML_ERROR_UNCLOSED_CDATA_SECTION},
2414 {19, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0", XML_ERROR_UNCLOSED_CDATA_SECTION},
2415 {20, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z", XML_ERROR_UNCLOSED_CDATA_SECTION},
2416 /* Now add a four-byte UTF-16 character */
2417 {21, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8",
2418 XML_ERROR_UNCLOSED_CDATA_SECTION},
2419 {22, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8\x34", XML_ERROR_PARTIAL_CHAR},
2420 {23, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8\x34\xdd",
2421 XML_ERROR_PARTIAL_CHAR},
2422 {24, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8\x34\xdd\x5e",
2423 XML_ERROR_UNCLOSED_CDATA_SECTION}};
2424 size_t i;
2425
2426 for (i = 0; i < sizeof(cases) / sizeof(struct CaseData); i++) {
2427 enum XML_Status actual_status;
2428 enum XML_Error actual_error;
2429
2430 if (_XML_Parse_SINGLE_BYTES(g_parser, prolog, (int)sizeof(prolog) - 1,
2431 XML_FALSE)
2432 == XML_STATUS_ERROR)
2433 xml_failure(g_parser);
2434 actual_status = _XML_Parse_SINGLE_BYTES(g_parser, cases[i].text,
2435 (int)cases[i].text_bytes, XML_TRUE);
2436 assert(actual_status == XML_STATUS_ERROR);
2437 actual_error = XML_GetErrorCode(g_parser);
2438 if (actual_error != cases[i].expected_error) {
2439 char message[1024];
2440
2441 sprintf(message,
2442 "Expected error %d (%" XML_FMT_STR "), got %d (%" XML_FMT_STR
2443 ") for case %lu\n",
2444 cases[i].expected_error, XML_ErrorString(cases[i].expected_error),
2445 actual_error, XML_ErrorString(actual_error),
2446 (long unsigned)(i + 1));
2447 fail(message);
2448 }
2449 XML_ParserReset(g_parser, NULL);
2450 }
2451 }
2452 END_TEST
2453
2454 static const char *long_cdata_text
2455 = "<s><![CDATA["
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 "012345678901234567890123456789012345678901234567890123456789"
2476 "]]></s>";
2477
2478 /* Test stopping the parser in cdata handler */
START_TEST(test_stop_parser_between_cdata_calls)2479 START_TEST(test_stop_parser_between_cdata_calls) {
2480 const char *text = long_cdata_text;
2481
2482 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2483 resumable = XML_FALSE;
2484 expect_failure(text, XML_ERROR_ABORTED, "Parse not aborted in CDATA handler");
2485 }
2486 END_TEST
2487
2488 /* Test suspending the parser in cdata handler */
START_TEST(test_suspend_parser_between_cdata_calls)2489 START_TEST(test_suspend_parser_between_cdata_calls) {
2490 const char *text = long_cdata_text;
2491 enum XML_Status result;
2492
2493 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2494 resumable = XML_TRUE;
2495 result = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE);
2496 if (result != XML_STATUS_SUSPENDED) {
2497 if (result == XML_STATUS_ERROR)
2498 xml_failure(g_parser);
2499 fail("Parse not suspended in CDATA handler");
2500 }
2501 if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE)
2502 xml_failure(g_parser);
2503 }
2504 END_TEST
2505
2506 /* Test memory allocation functions */
START_TEST(test_memory_allocation)2507 START_TEST(test_memory_allocation) {
2508 char *buffer = (char *)XML_MemMalloc(g_parser, 256);
2509 char *p;
2510
2511 if (buffer == NULL) {
2512 fail("Allocation failed");
2513 } else {
2514 /* Try writing to memory; some OSes try to cheat! */
2515 buffer[0] = 'T';
2516 buffer[1] = 'E';
2517 buffer[2] = 'S';
2518 buffer[3] = 'T';
2519 buffer[4] = '\0';
2520 if (strcmp(buffer, "TEST") != 0) {
2521 fail("Memory not writable");
2522 } else {
2523 p = (char *)XML_MemRealloc(g_parser, buffer, 512);
2524 if (p == NULL) {
2525 fail("Reallocation failed");
2526 } else {
2527 /* Write again, just to be sure */
2528 buffer = p;
2529 buffer[0] = 'V';
2530 if (strcmp(buffer, "VEST") != 0) {
2531 fail("Reallocated memory not writable");
2532 }
2533 }
2534 }
2535 XML_MemFree(g_parser, buffer);
2536 }
2537 }
2538 END_TEST
2539
2540 static void XMLCALL
record_default_handler(void * userData,const XML_Char * s,int len)2541 record_default_handler(void *userData, const XML_Char *s, int len) {
2542 UNUSED_P(s);
2543 UNUSED_P(len);
2544 CharData_AppendXMLChars((CharData *)userData, XCS("D"), 1);
2545 }
2546
2547 static void XMLCALL
record_cdata_handler(void * userData,const XML_Char * s,int len)2548 record_cdata_handler(void *userData, const XML_Char *s, int len) {
2549 UNUSED_P(s);
2550 UNUSED_P(len);
2551 CharData_AppendXMLChars((CharData *)userData, XCS("C"), 1);
2552 XML_DefaultCurrent(g_parser);
2553 }
2554
2555 static void XMLCALL
record_cdata_nodefault_handler(void * userData,const XML_Char * s,int len)2556 record_cdata_nodefault_handler(void *userData, const XML_Char *s, int len) {
2557 UNUSED_P(s);
2558 UNUSED_P(len);
2559 CharData_AppendXMLChars((CharData *)userData, XCS("c"), 1);
2560 }
2561
2562 static void XMLCALL
record_skip_handler(void * userData,const XML_Char * entityName,int is_parameter_entity)2563 record_skip_handler(void *userData, const XML_Char *entityName,
2564 int is_parameter_entity) {
2565 UNUSED_P(entityName);
2566 CharData_AppendXMLChars((CharData *)userData,
2567 is_parameter_entity ? XCS("E") : XCS("e"), 1);
2568 }
2569
2570 /* Test XML_DefaultCurrent() passes handling on correctly */
START_TEST(test_default_current)2571 START_TEST(test_default_current) {
2572 const char *text = "<doc>hell]</doc>";
2573 const char *entity_text = "<!DOCTYPE doc [\n"
2574 "<!ENTITY entity '%'>\n"
2575 "]>\n"
2576 "<doc>&entity;</doc>";
2577 CharData storage;
2578
2579 XML_SetDefaultHandler(g_parser, record_default_handler);
2580 XML_SetCharacterDataHandler(g_parser, record_cdata_handler);
2581 CharData_Init(&storage);
2582 XML_SetUserData(g_parser, &storage);
2583 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2584 == XML_STATUS_ERROR)
2585 xml_failure(g_parser);
2586 CharData_CheckXMLChars(&storage, XCS("DCDCDCDCDCDD"));
2587
2588 /* Again, without the defaulting */
2589 XML_ParserReset(g_parser, NULL);
2590 XML_SetDefaultHandler(g_parser, record_default_handler);
2591 XML_SetCharacterDataHandler(g_parser, record_cdata_nodefault_handler);
2592 CharData_Init(&storage);
2593 XML_SetUserData(g_parser, &storage);
2594 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2595 == XML_STATUS_ERROR)
2596 xml_failure(g_parser);
2597 CharData_CheckXMLChars(&storage, XCS("DcccccD"));
2598
2599 /* Now with an internal entity to complicate matters */
2600 XML_ParserReset(g_parser, NULL);
2601 XML_SetDefaultHandler(g_parser, record_default_handler);
2602 XML_SetCharacterDataHandler(g_parser, record_cdata_handler);
2603 CharData_Init(&storage);
2604 XML_SetUserData(g_parser, &storage);
2605 if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text),
2606 XML_TRUE)
2607 == XML_STATUS_ERROR)
2608 xml_failure(g_parser);
2609 /* The default handler suppresses the entity */
2610 CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDDD"));
2611
2612 /* Again, with a skip handler */
2613 XML_ParserReset(g_parser, NULL);
2614 XML_SetDefaultHandler(g_parser, record_default_handler);
2615 XML_SetCharacterDataHandler(g_parser, record_cdata_handler);
2616 XML_SetSkippedEntityHandler(g_parser, record_skip_handler);
2617 CharData_Init(&storage);
2618 XML_SetUserData(g_parser, &storage);
2619 if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text),
2620 XML_TRUE)
2621 == XML_STATUS_ERROR)
2622 xml_failure(g_parser);
2623 /* The default handler suppresses the entity */
2624 CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDeD"));
2625
2626 /* This time, allow the entity through */
2627 XML_ParserReset(g_parser, NULL);
2628 XML_SetDefaultHandlerExpand(g_parser, record_default_handler);
2629 XML_SetCharacterDataHandler(g_parser, record_cdata_handler);
2630 CharData_Init(&storage);
2631 XML_SetUserData(g_parser, &storage);
2632 if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text),
2633 XML_TRUE)
2634 == XML_STATUS_ERROR)
2635 xml_failure(g_parser);
2636 CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDCDD"));
2637
2638 /* Finally, without passing the cdata to the default handler */
2639 XML_ParserReset(g_parser, NULL);
2640 XML_SetDefaultHandlerExpand(g_parser, record_default_handler);
2641 XML_SetCharacterDataHandler(g_parser, record_cdata_nodefault_handler);
2642 CharData_Init(&storage);
2643 XML_SetUserData(g_parser, &storage);
2644 if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text),
2645 XML_TRUE)
2646 == XML_STATUS_ERROR)
2647 xml_failure(g_parser);
2648 CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDcD"));
2649 }
2650 END_TEST
2651
2652 /* Test DTD element parsing code paths */
START_TEST(test_dtd_elements)2653 START_TEST(test_dtd_elements) {
2654 const char *text = "<!DOCTYPE doc [\n"
2655 "<!ELEMENT doc (chapter)>\n"
2656 "<!ELEMENT chapter (#PCDATA)>\n"
2657 "]>\n"
2658 "<doc><chapter>Wombats are go</chapter></doc>";
2659
2660 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
2661 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2662 == XML_STATUS_ERROR)
2663 xml_failure(g_parser);
2664 }
2665 END_TEST
2666
2667 static void XMLCALL
element_decl_check_model(void * userData,const XML_Char * name,XML_Content * model)2668 element_decl_check_model(void *userData, const XML_Char *name,
2669 XML_Content *model) {
2670 UNUSED_P(userData);
2671 uint32_t errorFlags = 0;
2672
2673 /* Expected model array structure is this:
2674 * [0] (type 6, quant 0)
2675 * [1] (type 5, quant 0)
2676 * [3] (type 4, quant 0, name "bar")
2677 * [4] (type 4, quant 0, name "foo")
2678 * [5] (type 4, quant 3, name "xyz")
2679 * [2] (type 4, quant 2, name "zebra")
2680 */
2681 errorFlags |= ((xcstrcmp(name, XCS("junk")) == 0) ? 0 : (1u << 0));
2682 errorFlags |= ((model != NULL) ? 0 : (1u << 1));
2683
2684 errorFlags |= ((model[0].type == XML_CTYPE_SEQ) ? 0 : (1u << 2));
2685 errorFlags |= ((model[0].quant == XML_CQUANT_NONE) ? 0 : (1u << 3));
2686 errorFlags |= ((model[0].numchildren == 2) ? 0 : (1u << 4));
2687 errorFlags |= ((model[0].children == &model[1]) ? 0 : (1u << 5));
2688 errorFlags |= ((model[0].name == NULL) ? 0 : (1u << 6));
2689
2690 errorFlags |= ((model[1].type == XML_CTYPE_CHOICE) ? 0 : (1u << 7));
2691 errorFlags |= ((model[1].quant == XML_CQUANT_NONE) ? 0 : (1u << 8));
2692 errorFlags |= ((model[1].numchildren == 3) ? 0 : (1u << 9));
2693 errorFlags |= ((model[1].children == &model[3]) ? 0 : (1u << 10));
2694 errorFlags |= ((model[1].name == NULL) ? 0 : (1u << 11));
2695
2696 errorFlags |= ((model[2].type == XML_CTYPE_NAME) ? 0 : (1u << 12));
2697 errorFlags |= ((model[2].quant == XML_CQUANT_REP) ? 0 : (1u << 13));
2698 errorFlags |= ((model[2].numchildren == 0) ? 0 : (1u << 14));
2699 errorFlags |= ((model[2].children == NULL) ? 0 : (1u << 15));
2700 errorFlags |= ((xcstrcmp(model[2].name, XCS("zebra")) == 0) ? 0 : (1u << 16));
2701
2702 errorFlags |= ((model[3].type == XML_CTYPE_NAME) ? 0 : (1u << 17));
2703 errorFlags |= ((model[3].quant == XML_CQUANT_NONE) ? 0 : (1u << 18));
2704 errorFlags |= ((model[3].numchildren == 0) ? 0 : (1u << 19));
2705 errorFlags |= ((model[3].children == NULL) ? 0 : (1u << 20));
2706 errorFlags |= ((xcstrcmp(model[3].name, XCS("bar")) == 0) ? 0 : (1u << 21));
2707
2708 errorFlags |= ((model[4].type == XML_CTYPE_NAME) ? 0 : (1u << 22));
2709 errorFlags |= ((model[4].quant == XML_CQUANT_NONE) ? 0 : (1u << 23));
2710 errorFlags |= ((model[4].numchildren == 0) ? 0 : (1u << 24));
2711 errorFlags |= ((model[4].children == NULL) ? 0 : (1u << 25));
2712 errorFlags |= ((xcstrcmp(model[4].name, XCS("foo")) == 0) ? 0 : (1u << 26));
2713
2714 errorFlags |= ((model[5].type == XML_CTYPE_NAME) ? 0 : (1u << 27));
2715 errorFlags |= ((model[5].quant == XML_CQUANT_PLUS) ? 0 : (1u << 28));
2716 errorFlags |= ((model[5].numchildren == 0) ? 0 : (1u << 29));
2717 errorFlags |= ((model[5].children == NULL) ? 0 : (1u << 30));
2718 errorFlags |= ((xcstrcmp(model[5].name, XCS("xyz")) == 0) ? 0 : (1u << 31));
2719
2720 XML_SetUserData(g_parser, (void *)(uintptr_t)errorFlags);
2721 XML_FreeContentModel(g_parser, model);
2722 }
2723
START_TEST(test_dtd_elements_nesting)2724 START_TEST(test_dtd_elements_nesting) {
2725 // Payload inspired by a test in Perl's XML::Parser
2726 const char *text = "<!DOCTYPE foo [\n"
2727 "<!ELEMENT junk ((bar|foo|xyz+), zebra*)>\n"
2728 "]>\n"
2729 "<foo/>";
2730
2731 XML_SetUserData(g_parser, (void *)(uintptr_t)-1);
2732
2733 XML_SetElementDeclHandler(g_parser, element_decl_check_model);
2734 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
2735 == XML_STATUS_ERROR)
2736 xml_failure(g_parser);
2737
2738 if ((uint32_t)(uintptr_t)XML_GetUserData(g_parser) != 0)
2739 fail("Element declaration model regression detected");
2740 }
2741 END_TEST
2742
2743 /* Test foreign DTD handling */
START_TEST(test_set_foreign_dtd)2744 START_TEST(test_set_foreign_dtd) {
2745 const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n";
2746 const char *text2 = "<doc>&entity;</doc>";
2747 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
2748
2749 /* Check hash salt is passed through too */
2750 XML_SetHashSalt(g_parser, 0x12345678);
2751 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2752 XML_SetUserData(g_parser, &test_data);
2753 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
2754 /* Add a default handler to exercise more code paths */
2755 XML_SetDefaultHandler(g_parser, dummy_default_handler);
2756 if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE)
2757 fail("Could not set foreign DTD");
2758 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
2759 == XML_STATUS_ERROR)
2760 xml_failure(g_parser);
2761
2762 /* Ensure that trying to set the DTD after parsing has started
2763 * is faulted, even if it's the same setting.
2764 */
2765 if (XML_UseForeignDTD(g_parser, XML_TRUE)
2766 != XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING)
2767 fail("Failed to reject late foreign DTD setting");
2768 /* Ditto for the hash salt */
2769 if (XML_SetHashSalt(g_parser, 0x23456789))
2770 fail("Failed to reject late hash salt change");
2771
2772 /* Now finish the parse */
2773 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
2774 == XML_STATUS_ERROR)
2775 xml_failure(g_parser);
2776 }
2777 END_TEST
2778
2779 /* Test foreign DTD handling with a failing NotStandalone handler */
START_TEST(test_foreign_dtd_not_standalone)2780 START_TEST(test_foreign_dtd_not_standalone) {
2781 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
2782 "<doc>&entity;</doc>";
2783 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
2784
2785 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2786 XML_SetUserData(g_parser, &test_data);
2787 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
2788 XML_SetNotStandaloneHandler(g_parser, reject_not_standalone_handler);
2789 if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE)
2790 fail("Could not set foreign DTD");
2791 expect_failure(text, XML_ERROR_NOT_STANDALONE,
2792 "NotStandalonehandler failed to reject");
2793 }
2794 END_TEST
2795
2796 /* Test invalid character in a foreign DTD is faulted */
START_TEST(test_invalid_foreign_dtd)2797 START_TEST(test_invalid_foreign_dtd) {
2798 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
2799 "<doc>&entity;</doc>";
2800 ExtFaults test_data
2801 = {"$", "Dollar not faulted", NULL, XML_ERROR_INVALID_TOKEN};
2802
2803 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2804 XML_SetUserData(g_parser, &test_data);
2805 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
2806 XML_UseForeignDTD(g_parser, XML_TRUE);
2807 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
2808 "Bad DTD should not have been accepted");
2809 }
2810 END_TEST
2811
2812 /* Test foreign DTD use with a doctype */
START_TEST(test_foreign_dtd_with_doctype)2813 START_TEST(test_foreign_dtd_with_doctype) {
2814 const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n"
2815 "<!DOCTYPE doc [<!ENTITY entity 'hello world'>]>\n";
2816 const char *text2 = "<doc>&entity;</doc>";
2817 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
2818
2819 /* Check hash salt is passed through too */
2820 XML_SetHashSalt(g_parser, 0x12345678);
2821 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2822 XML_SetUserData(g_parser, &test_data);
2823 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
2824 /* Add a default handler to exercise more code paths */
2825 XML_SetDefaultHandler(g_parser, dummy_default_handler);
2826 if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE)
2827 fail("Could not set foreign DTD");
2828 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
2829 == XML_STATUS_ERROR)
2830 xml_failure(g_parser);
2831
2832 /* Ensure that trying to set the DTD after parsing has started
2833 * is faulted, even if it's the same setting.
2834 */
2835 if (XML_UseForeignDTD(g_parser, XML_TRUE)
2836 != XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING)
2837 fail("Failed to reject late foreign DTD setting");
2838 /* Ditto for the hash salt */
2839 if (XML_SetHashSalt(g_parser, 0x23456789))
2840 fail("Failed to reject late hash salt change");
2841
2842 /* Now finish the parse */
2843 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
2844 == XML_STATUS_ERROR)
2845 xml_failure(g_parser);
2846 }
2847 END_TEST
2848
2849 /* Test XML_UseForeignDTD with no external subset present */
2850 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)2851 external_entity_null_loader(XML_Parser parser, const XML_Char *context,
2852 const XML_Char *base, const XML_Char *systemId,
2853 const XML_Char *publicId) {
2854 UNUSED_P(parser);
2855 UNUSED_P(context);
2856 UNUSED_P(base);
2857 UNUSED_P(systemId);
2858 UNUSED_P(publicId);
2859 return XML_STATUS_OK;
2860 }
2861
START_TEST(test_foreign_dtd_without_external_subset)2862 START_TEST(test_foreign_dtd_without_external_subset) {
2863 const char *text = "<!DOCTYPE doc [<!ENTITY foo 'bar'>]>\n"
2864 "<doc>&foo;</doc>";
2865
2866 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2867 XML_SetUserData(g_parser, NULL);
2868 XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader);
2869 XML_UseForeignDTD(g_parser, XML_TRUE);
2870 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2871 == XML_STATUS_ERROR)
2872 xml_failure(g_parser);
2873 }
2874 END_TEST
2875
START_TEST(test_empty_foreign_dtd)2876 START_TEST(test_empty_foreign_dtd) {
2877 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
2878 "<doc>&entity;</doc>";
2879
2880 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2881 XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader);
2882 XML_UseForeignDTD(g_parser, XML_TRUE);
2883 expect_failure(text, XML_ERROR_UNDEFINED_ENTITY,
2884 "Undefined entity not faulted");
2885 }
2886 END_TEST
2887
2888 /* Test XML Base is set and unset appropriately */
START_TEST(test_set_base)2889 START_TEST(test_set_base) {
2890 const XML_Char *old_base;
2891 const XML_Char *new_base = XCS("/local/file/name.xml");
2892
2893 old_base = XML_GetBase(g_parser);
2894 if (XML_SetBase(g_parser, new_base) != XML_STATUS_OK)
2895 fail("Unable to set base");
2896 if (xcstrcmp(XML_GetBase(g_parser), new_base) != 0)
2897 fail("Base setting not correct");
2898 if (XML_SetBase(g_parser, NULL) != XML_STATUS_OK)
2899 fail("Unable to NULL base");
2900 if (XML_GetBase(g_parser) != NULL)
2901 fail("Base setting not nulled");
2902 XML_SetBase(g_parser, old_base);
2903 }
2904 END_TEST
2905
2906 /* Test attribute counts, indexing, etc */
2907 typedef struct attrInfo {
2908 const XML_Char *name;
2909 const XML_Char *value;
2910 } AttrInfo;
2911
2912 typedef struct elementInfo {
2913 const XML_Char *name;
2914 int attr_count;
2915 const XML_Char *id_name;
2916 AttrInfo *attributes;
2917 } ElementInfo;
2918
2919 static void XMLCALL
counting_start_element_handler(void * userData,const XML_Char * name,const XML_Char ** atts)2920 counting_start_element_handler(void *userData, const XML_Char *name,
2921 const XML_Char **atts) {
2922 ElementInfo *info = (ElementInfo *)userData;
2923 AttrInfo *attr;
2924 int count, id, i;
2925
2926 while (info->name != NULL) {
2927 if (! xcstrcmp(name, info->name))
2928 break;
2929 info++;
2930 }
2931 if (info->name == NULL)
2932 fail("Element not recognised");
2933 /* The attribute count is twice what you might expect. It is a
2934 * count of items in atts, an array which contains alternating
2935 * attribute names and attribute values. For the naive user this
2936 * is possibly a little unexpected, but it is what the
2937 * documentation in expat.h tells us to expect.
2938 */
2939 count = XML_GetSpecifiedAttributeCount(g_parser);
2940 if (info->attr_count * 2 != count) {
2941 fail("Not got expected attribute count");
2942 return;
2943 }
2944 id = XML_GetIdAttributeIndex(g_parser);
2945 if (id == -1 && info->id_name != NULL) {
2946 fail("ID not present");
2947 return;
2948 }
2949 if (id != -1 && xcstrcmp(atts[id], info->id_name)) {
2950 fail("ID does not have the correct name");
2951 return;
2952 }
2953 for (i = 0; i < info->attr_count; i++) {
2954 attr = info->attributes;
2955 while (attr->name != NULL) {
2956 if (! xcstrcmp(atts[0], attr->name))
2957 break;
2958 attr++;
2959 }
2960 if (attr->name == NULL) {
2961 fail("Attribute not recognised");
2962 return;
2963 }
2964 if (xcstrcmp(atts[1], attr->value)) {
2965 fail("Attribute has wrong value");
2966 return;
2967 }
2968 /* Remember, two entries in atts per attribute (see above) */
2969 atts += 2;
2970 }
2971 }
2972
START_TEST(test_attributes)2973 START_TEST(test_attributes) {
2974 const char *text = "<!DOCTYPE doc [\n"
2975 "<!ELEMENT doc (tag)>\n"
2976 "<!ATTLIST doc id ID #REQUIRED>\n"
2977 "]>"
2978 "<doc a='1' id='one' b='2'>"
2979 "<tag c='3'/>"
2980 "</doc>";
2981 AttrInfo doc_info[] = {{XCS("a"), XCS("1")},
2982 {XCS("b"), XCS("2")},
2983 {XCS("id"), XCS("one")},
2984 {NULL, NULL}};
2985 AttrInfo tag_info[] = {{XCS("c"), XCS("3")}, {NULL, NULL}};
2986 ElementInfo info[] = {{XCS("doc"), 3, XCS("id"), NULL},
2987 {XCS("tag"), 1, NULL, NULL},
2988 {NULL, 0, NULL, NULL}};
2989 info[0].attributes = doc_info;
2990 info[1].attributes = tag_info;
2991
2992 XML_SetStartElementHandler(g_parser, counting_start_element_handler);
2993 XML_SetUserData(g_parser, info);
2994 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2995 == XML_STATUS_ERROR)
2996 xml_failure(g_parser);
2997 }
2998 END_TEST
2999
3000 /* Test reset works correctly in the middle of processing an internal
3001 * entity. Exercises some obscure code in XML_ParserReset().
3002 */
START_TEST(test_reset_in_entity)3003 START_TEST(test_reset_in_entity) {
3004 const char *text = "<!DOCTYPE doc [\n"
3005 "<!ENTITY wombat 'wom'>\n"
3006 "<!ENTITY entity 'hi &wom; there'>\n"
3007 "]>\n"
3008 "<doc>&entity;</doc>";
3009 XML_ParsingStatus status;
3010
3011 resumable = XML_TRUE;
3012 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
3013 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
3014 == XML_STATUS_ERROR)
3015 xml_failure(g_parser);
3016 XML_GetParsingStatus(g_parser, &status);
3017 if (status.parsing != XML_SUSPENDED)
3018 fail("Parsing status not SUSPENDED");
3019 XML_ParserReset(g_parser, NULL);
3020 XML_GetParsingStatus(g_parser, &status);
3021 if (status.parsing != XML_INITIALIZED)
3022 fail("Parsing status doesn't reset to INITIALIZED");
3023 }
3024 END_TEST
3025
3026 /* Test that resume correctly passes through parse errors */
START_TEST(test_resume_invalid_parse)3027 START_TEST(test_resume_invalid_parse) {
3028 const char *text = "<doc>Hello</doc"; /* Missing closing wedge */
3029
3030 resumable = XML_TRUE;
3031 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
3032 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
3033 == XML_STATUS_ERROR)
3034 xml_failure(g_parser);
3035 if (XML_ResumeParser(g_parser) == XML_STATUS_OK)
3036 fail("Resumed invalid parse not faulted");
3037 if (XML_GetErrorCode(g_parser) != XML_ERROR_UNCLOSED_TOKEN)
3038 fail("Invalid parse not correctly faulted");
3039 }
3040 END_TEST
3041
3042 /* Test that re-suspended parses are correctly passed through */
START_TEST(test_resume_resuspended)3043 START_TEST(test_resume_resuspended) {
3044 const char *text = "<doc>Hello<meep/>world</doc>";
3045
3046 resumable = XML_TRUE;
3047 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
3048 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
3049 == XML_STATUS_ERROR)
3050 xml_failure(g_parser);
3051 resumable = XML_TRUE;
3052 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
3053 if (XML_ResumeParser(g_parser) != XML_STATUS_SUSPENDED)
3054 fail("Resumption not suspended");
3055 /* This one should succeed and finish up */
3056 if (XML_ResumeParser(g_parser) != XML_STATUS_OK)
3057 xml_failure(g_parser);
3058 }
3059 END_TEST
3060
3061 /* Test that CDATA shows up correctly through a default handler */
START_TEST(test_cdata_default)3062 START_TEST(test_cdata_default) {
3063 const char *text = "<doc><![CDATA[Hello\nworld]]></doc>";
3064 const XML_Char *expected = XCS("<doc><![CDATA[Hello\nworld]]></doc>");
3065 CharData storage;
3066
3067 CharData_Init(&storage);
3068 XML_SetUserData(g_parser, &storage);
3069 XML_SetDefaultHandler(g_parser, accumulate_characters);
3070
3071 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3072 == XML_STATUS_ERROR)
3073 xml_failure(g_parser);
3074 CharData_CheckXMLChars(&storage, expected);
3075 }
3076 END_TEST
3077
3078 /* Test resetting a subordinate parser does exactly nothing */
3079 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)3080 external_entity_resetter(XML_Parser parser, const XML_Char *context,
3081 const XML_Char *base, const XML_Char *systemId,
3082 const XML_Char *publicId) {
3083 const char *text = "<!ELEMENT doc (#PCDATA)*>";
3084 XML_Parser ext_parser;
3085 XML_ParsingStatus status;
3086
3087 UNUSED_P(base);
3088 UNUSED_P(systemId);
3089 UNUSED_P(publicId);
3090 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3091 if (ext_parser == NULL)
3092 fail("Could not create external entity parser");
3093 XML_GetParsingStatus(ext_parser, &status);
3094 if (status.parsing != XML_INITIALIZED) {
3095 fail("Parsing status is not INITIALIZED");
3096 return XML_STATUS_ERROR;
3097 }
3098 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3099 == XML_STATUS_ERROR) {
3100 xml_failure(parser);
3101 return XML_STATUS_ERROR;
3102 }
3103 XML_GetParsingStatus(ext_parser, &status);
3104 if (status.parsing != XML_FINISHED) {
3105 fail("Parsing status is not FINISHED");
3106 return XML_STATUS_ERROR;
3107 }
3108 /* Check we can't parse here */
3109 if (XML_Parse(ext_parser, text, (int)strlen(text), XML_TRUE)
3110 != XML_STATUS_ERROR)
3111 fail("Parsing when finished not faulted");
3112 if (XML_GetErrorCode(ext_parser) != XML_ERROR_FINISHED)
3113 fail("Parsing when finished faulted with wrong code");
3114 XML_ParserReset(ext_parser, NULL);
3115 XML_GetParsingStatus(ext_parser, &status);
3116 if (status.parsing != XML_FINISHED) {
3117 fail("Parsing status not still FINISHED");
3118 return XML_STATUS_ERROR;
3119 }
3120 XML_ParserFree(ext_parser);
3121 return XML_STATUS_OK;
3122 }
3123
START_TEST(test_subordinate_reset)3124 START_TEST(test_subordinate_reset) {
3125 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
3126 "<!DOCTYPE doc SYSTEM 'foo'>\n"
3127 "<doc>&entity;</doc>";
3128
3129 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3130 XML_SetExternalEntityRefHandler(g_parser, external_entity_resetter);
3131 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3132 == XML_STATUS_ERROR)
3133 xml_failure(g_parser);
3134 }
3135 END_TEST
3136
3137 /* Test suspending a subordinate parser */
3138
3139 static void XMLCALL
entity_suspending_decl_handler(void * userData,const XML_Char * name,XML_Content * model)3140 entity_suspending_decl_handler(void *userData, const XML_Char *name,
3141 XML_Content *model) {
3142 XML_Parser ext_parser = (XML_Parser)userData;
3143
3144 UNUSED_P(name);
3145 if (XML_StopParser(ext_parser, XML_TRUE) != XML_STATUS_ERROR)
3146 fail("Attempting to suspend a subordinate parser not faulted");
3147 if (XML_GetErrorCode(ext_parser) != XML_ERROR_SUSPEND_PE)
3148 fail("Suspending subordinate parser get wrong code");
3149 XML_SetElementDeclHandler(ext_parser, NULL);
3150 XML_FreeContentModel(g_parser, model);
3151 }
3152
3153 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)3154 external_entity_suspender(XML_Parser parser, const XML_Char *context,
3155 const XML_Char *base, const XML_Char *systemId,
3156 const XML_Char *publicId) {
3157 const char *text = "<!ELEMENT doc (#PCDATA)*>";
3158 XML_Parser ext_parser;
3159
3160 UNUSED_P(base);
3161 UNUSED_P(systemId);
3162 UNUSED_P(publicId);
3163 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3164 if (ext_parser == NULL)
3165 fail("Could not create external entity parser");
3166 XML_SetElementDeclHandler(ext_parser, entity_suspending_decl_handler);
3167 XML_SetUserData(ext_parser, ext_parser);
3168 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3169 == XML_STATUS_ERROR) {
3170 xml_failure(ext_parser);
3171 return XML_STATUS_ERROR;
3172 }
3173 XML_ParserFree(ext_parser);
3174 return XML_STATUS_OK;
3175 }
3176
START_TEST(test_subordinate_suspend)3177 START_TEST(test_subordinate_suspend) {
3178 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
3179 "<!DOCTYPE doc SYSTEM 'foo'>\n"
3180 "<doc>&entity;</doc>";
3181
3182 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3183 XML_SetExternalEntityRefHandler(g_parser, external_entity_suspender);
3184 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3185 == XML_STATUS_ERROR)
3186 xml_failure(g_parser);
3187 }
3188 END_TEST
3189
3190 /* Test suspending a subordinate parser from an XML declaration */
3191 /* Increases code coverage of the tests */
3192 static void XMLCALL
entity_suspending_xdecl_handler(void * userData,const XML_Char * version,const XML_Char * encoding,int standalone)3193 entity_suspending_xdecl_handler(void *userData, const XML_Char *version,
3194 const XML_Char *encoding, int standalone) {
3195 XML_Parser ext_parser = (XML_Parser)userData;
3196
3197 UNUSED_P(version);
3198 UNUSED_P(encoding);
3199 UNUSED_P(standalone);
3200 XML_StopParser(ext_parser, resumable);
3201 XML_SetXmlDeclHandler(ext_parser, NULL);
3202 }
3203
3204 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)3205 external_entity_suspend_xmldecl(XML_Parser parser, const XML_Char *context,
3206 const XML_Char *base, const XML_Char *systemId,
3207 const XML_Char *publicId) {
3208 const char *text = "<?xml version='1.0' encoding='us-ascii'?>";
3209 XML_Parser ext_parser;
3210 XML_ParsingStatus status;
3211 enum XML_Status rc;
3212
3213 UNUSED_P(base);
3214 UNUSED_P(systemId);
3215 UNUSED_P(publicId);
3216 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3217 if (ext_parser == NULL)
3218 fail("Could not create external entity parser");
3219 XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
3220 XML_SetUserData(ext_parser, ext_parser);
3221 rc = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
3222 XML_GetParsingStatus(ext_parser, &status);
3223 if (resumable) {
3224 if (rc == XML_STATUS_ERROR)
3225 xml_failure(ext_parser);
3226 if (status.parsing != XML_SUSPENDED)
3227 fail("Ext Parsing status not SUSPENDED");
3228 } else {
3229 if (rc != XML_STATUS_ERROR)
3230 fail("Ext parsing not aborted");
3231 if (XML_GetErrorCode(ext_parser) != XML_ERROR_ABORTED)
3232 xml_failure(ext_parser);
3233 if (status.parsing != XML_FINISHED)
3234 fail("Ext Parsing status not FINISHED");
3235 }
3236
3237 XML_ParserFree(ext_parser);
3238 return XML_STATUS_OK;
3239 }
3240
START_TEST(test_subordinate_xdecl_suspend)3241 START_TEST(test_subordinate_xdecl_suspend) {
3242 const char *text
3243 = "<!DOCTYPE doc [\n"
3244 " <!ENTITY entity SYSTEM 'http://example.org/dummy.ent'>\n"
3245 "]>\n"
3246 "<doc>&entity;</doc>";
3247
3248 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3249 XML_SetExternalEntityRefHandler(g_parser, external_entity_suspend_xmldecl);
3250 resumable = XML_TRUE;
3251 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3252 == XML_STATUS_ERROR)
3253 xml_failure(g_parser);
3254 }
3255 END_TEST
3256
START_TEST(test_subordinate_xdecl_abort)3257 START_TEST(test_subordinate_xdecl_abort) {
3258 const char *text
3259 = "<!DOCTYPE doc [\n"
3260 " <!ENTITY entity SYSTEM 'http://example.org/dummy.ent'>\n"
3261 "]>\n"
3262 "<doc>&entity;</doc>";
3263
3264 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3265 XML_SetExternalEntityRefHandler(g_parser, external_entity_suspend_xmldecl);
3266 resumable = XML_FALSE;
3267 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3268 == XML_STATUS_ERROR)
3269 xml_failure(g_parser);
3270 }
3271 END_TEST
3272
3273 /* Test external entity fault handling with suspension */
3274 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)3275 external_entity_suspending_faulter(XML_Parser parser, const XML_Char *context,
3276 const XML_Char *base,
3277 const XML_Char *systemId,
3278 const XML_Char *publicId) {
3279 XML_Parser ext_parser;
3280 ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser);
3281 void *buffer;
3282 int parse_len = (int)strlen(fault->parse_text);
3283
3284 UNUSED_P(base);
3285 UNUSED_P(systemId);
3286 UNUSED_P(publicId);
3287 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3288 if (ext_parser == NULL)
3289 fail("Could not create external entity parser");
3290 XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
3291 XML_SetUserData(ext_parser, ext_parser);
3292 resumable = XML_TRUE;
3293 buffer = XML_GetBuffer(ext_parser, parse_len);
3294 if (buffer == NULL)
3295 fail("Could not allocate parse buffer");
3296 assert(buffer != NULL);
3297 memcpy(buffer, fault->parse_text, parse_len);
3298 if (XML_ParseBuffer(ext_parser, parse_len, XML_FALSE) != XML_STATUS_SUSPENDED)
3299 fail("XML declaration did not suspend");
3300 if (XML_ResumeParser(ext_parser) != XML_STATUS_OK)
3301 xml_failure(ext_parser);
3302 if (XML_ParseBuffer(ext_parser, 0, XML_TRUE) != XML_STATUS_ERROR)
3303 fail(fault->fail_text);
3304 if (XML_GetErrorCode(ext_parser) != fault->error)
3305 xml_failure(ext_parser);
3306
3307 XML_ParserFree(ext_parser);
3308 return XML_STATUS_ERROR;
3309 }
3310
START_TEST(test_ext_entity_invalid_suspended_parse)3311 START_TEST(test_ext_entity_invalid_suspended_parse) {
3312 const char *text = "<!DOCTYPE doc [\n"
3313 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
3314 "]>\n"
3315 "<doc>&en;</doc>";
3316 ExtFaults faults[]
3317 = {{"<?xml version='1.0' encoding='us-ascii'?><",
3318 "Incomplete element declaration not faulted", NULL,
3319 XML_ERROR_UNCLOSED_TOKEN},
3320 {/* First two bytes of a three-byte char */
3321 "<?xml version='1.0' encoding='utf-8'?>\xe2\x82",
3322 "Incomplete character not faulted", NULL, XML_ERROR_PARTIAL_CHAR},
3323 {NULL, NULL, NULL, XML_ERROR_NONE}};
3324 ExtFaults *fault;
3325
3326 for (fault = &faults[0]; fault->parse_text != NULL; fault++) {
3327 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3328 XML_SetExternalEntityRefHandler(g_parser,
3329 external_entity_suspending_faulter);
3330 XML_SetUserData(g_parser, fault);
3331 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
3332 "Parser did not report external entity error");
3333 XML_ParserReset(g_parser, NULL);
3334 }
3335 }
3336 END_TEST
3337
3338 /* Test setting an explicit encoding */
START_TEST(test_explicit_encoding)3339 START_TEST(test_explicit_encoding) {
3340 const char *text1 = "<doc>Hello ";
3341 const char *text2 = " World</doc>";
3342
3343 /* Just check that we can set the encoding to NULL before starting */
3344 if (XML_SetEncoding(g_parser, NULL) != XML_STATUS_OK)
3345 fail("Failed to initialise encoding to NULL");
3346 /* Say we are UTF-8 */
3347 if (XML_SetEncoding(g_parser, XCS("utf-8")) != XML_STATUS_OK)
3348 fail("Failed to set explicit encoding");
3349 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
3350 == XML_STATUS_ERROR)
3351 xml_failure(g_parser);
3352 /* Try to switch encodings mid-parse */
3353 if (XML_SetEncoding(g_parser, XCS("us-ascii")) != XML_STATUS_ERROR)
3354 fail("Allowed encoding change");
3355 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
3356 == XML_STATUS_ERROR)
3357 xml_failure(g_parser);
3358 /* Try now the parse is over */
3359 if (XML_SetEncoding(g_parser, NULL) != XML_STATUS_OK)
3360 fail("Failed to unset encoding");
3361 }
3362 END_TEST
3363
3364 /* Test handling of trailing CR (rather than newline) */
3365 static void XMLCALL
cr_cdata_handler(void * userData,const XML_Char * s,int len)3366 cr_cdata_handler(void *userData, const XML_Char *s, int len) {
3367 int *pfound = (int *)userData;
3368
3369 /* Internal processing turns the CR into a newline for the
3370 * character data handler, but not for the default handler
3371 */
3372 if (len == 1 && (*s == XCS('\n') || *s == XCS('\r')))
3373 *pfound = 1;
3374 }
3375
START_TEST(test_trailing_cr)3376 START_TEST(test_trailing_cr) {
3377 const char *text = "<doc>\r";
3378 int found_cr;
3379
3380 /* Try with a character handler, for code coverage */
3381 XML_SetCharacterDataHandler(g_parser, cr_cdata_handler);
3382 XML_SetUserData(g_parser, &found_cr);
3383 found_cr = 0;
3384 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3385 == XML_STATUS_OK)
3386 fail("Failed to fault unclosed doc");
3387 if (found_cr == 0)
3388 fail("Did not catch the carriage return");
3389 XML_ParserReset(g_parser, NULL);
3390
3391 /* Now with a default handler instead */
3392 XML_SetDefaultHandler(g_parser, cr_cdata_handler);
3393 XML_SetUserData(g_parser, &found_cr);
3394 found_cr = 0;
3395 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3396 == XML_STATUS_OK)
3397 fail("Failed to fault unclosed doc");
3398 if (found_cr == 0)
3399 fail("Did not catch default carriage return");
3400 }
3401 END_TEST
3402
3403 /* Test trailing CR in an external entity parse */
3404 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)3405 external_entity_cr_catcher(XML_Parser parser, const XML_Char *context,
3406 const XML_Char *base, const XML_Char *systemId,
3407 const XML_Char *publicId) {
3408 const char *text = "\r";
3409 XML_Parser ext_parser;
3410
3411 UNUSED_P(base);
3412 UNUSED_P(systemId);
3413 UNUSED_P(publicId);
3414 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3415 if (ext_parser == NULL)
3416 fail("Could not create external entity parser");
3417 XML_SetCharacterDataHandler(ext_parser, cr_cdata_handler);
3418 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3419 == XML_STATUS_ERROR)
3420 xml_failure(ext_parser);
3421 XML_ParserFree(ext_parser);
3422 return XML_STATUS_OK;
3423 }
3424
3425 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)3426 external_entity_bad_cr_catcher(XML_Parser parser, const XML_Char *context,
3427 const XML_Char *base, const XML_Char *systemId,
3428 const XML_Char *publicId) {
3429 const char *text = "<tag>\r";
3430 XML_Parser ext_parser;
3431
3432 UNUSED_P(base);
3433 UNUSED_P(systemId);
3434 UNUSED_P(publicId);
3435 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3436 if (ext_parser == NULL)
3437 fail("Could not create external entity parser");
3438 XML_SetCharacterDataHandler(ext_parser, cr_cdata_handler);
3439 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3440 == XML_STATUS_OK)
3441 fail("Async entity error not caught");
3442 if (XML_GetErrorCode(ext_parser) != XML_ERROR_ASYNC_ENTITY)
3443 xml_failure(ext_parser);
3444 XML_ParserFree(ext_parser);
3445 return XML_STATUS_OK;
3446 }
3447
START_TEST(test_ext_entity_trailing_cr)3448 START_TEST(test_ext_entity_trailing_cr) {
3449 const char *text = "<!DOCTYPE doc [\n"
3450 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
3451 "]>\n"
3452 "<doc>&en;</doc>";
3453 int found_cr;
3454
3455 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3456 XML_SetExternalEntityRefHandler(g_parser, external_entity_cr_catcher);
3457 XML_SetUserData(g_parser, &found_cr);
3458 found_cr = 0;
3459 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3460 != XML_STATUS_OK)
3461 xml_failure(g_parser);
3462 if (found_cr == 0)
3463 fail("No carriage return found");
3464 XML_ParserReset(g_parser, NULL);
3465
3466 /* Try again with a different trailing CR */
3467 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3468 XML_SetExternalEntityRefHandler(g_parser, external_entity_bad_cr_catcher);
3469 XML_SetUserData(g_parser, &found_cr);
3470 found_cr = 0;
3471 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3472 != XML_STATUS_OK)
3473 xml_failure(g_parser);
3474 if (found_cr == 0)
3475 fail("No carriage return found");
3476 }
3477 END_TEST
3478
3479 /* Test handling of trailing square bracket */
3480 static void XMLCALL
rsqb_handler(void * userData,const XML_Char * s,int len)3481 rsqb_handler(void *userData, const XML_Char *s, int len) {
3482 int *pfound = (int *)userData;
3483
3484 if (len == 1 && *s == XCS(']'))
3485 *pfound = 1;
3486 }
3487
START_TEST(test_trailing_rsqb)3488 START_TEST(test_trailing_rsqb) {
3489 const char *text8 = "<doc>]";
3490 const char text16[] = "\xFF\xFE<\000d\000o\000c\000>\000]\000";
3491 int found_rsqb;
3492 int text8_len = (int)strlen(text8);
3493
3494 XML_SetCharacterDataHandler(g_parser, rsqb_handler);
3495 XML_SetUserData(g_parser, &found_rsqb);
3496 found_rsqb = 0;
3497 if (_XML_Parse_SINGLE_BYTES(g_parser, text8, text8_len, XML_TRUE)
3498 == XML_STATUS_OK)
3499 fail("Failed to fault unclosed doc");
3500 if (found_rsqb == 0)
3501 fail("Did not catch the right square bracket");
3502
3503 /* Try again with a different encoding */
3504 XML_ParserReset(g_parser, NULL);
3505 XML_SetCharacterDataHandler(g_parser, rsqb_handler);
3506 XML_SetUserData(g_parser, &found_rsqb);
3507 found_rsqb = 0;
3508 if (_XML_Parse_SINGLE_BYTES(g_parser, text16, (int)sizeof(text16) - 1,
3509 XML_TRUE)
3510 == XML_STATUS_OK)
3511 fail("Failed to fault unclosed doc");
3512 if (found_rsqb == 0)
3513 fail("Did not catch the right square bracket");
3514
3515 /* And finally with a default handler */
3516 XML_ParserReset(g_parser, NULL);
3517 XML_SetDefaultHandler(g_parser, rsqb_handler);
3518 XML_SetUserData(g_parser, &found_rsqb);
3519 found_rsqb = 0;
3520 if (_XML_Parse_SINGLE_BYTES(g_parser, text16, (int)sizeof(text16) - 1,
3521 XML_TRUE)
3522 == XML_STATUS_OK)
3523 fail("Failed to fault unclosed doc");
3524 if (found_rsqb == 0)
3525 fail("Did not catch the right square bracket");
3526 }
3527 END_TEST
3528
3529 /* Test trailing right square bracket in an external entity parse */
3530 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)3531 external_entity_rsqb_catcher(XML_Parser parser, const XML_Char *context,
3532 const XML_Char *base, const XML_Char *systemId,
3533 const XML_Char *publicId) {
3534 const char *text = "<tag>]";
3535 XML_Parser ext_parser;
3536
3537 UNUSED_P(base);
3538 UNUSED_P(systemId);
3539 UNUSED_P(publicId);
3540 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3541 if (ext_parser == NULL)
3542 fail("Could not create external entity parser");
3543 XML_SetCharacterDataHandler(ext_parser, rsqb_handler);
3544 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3545 != XML_STATUS_ERROR)
3546 fail("Async entity error not caught");
3547 if (XML_GetErrorCode(ext_parser) != XML_ERROR_ASYNC_ENTITY)
3548 xml_failure(ext_parser);
3549 XML_ParserFree(ext_parser);
3550 return XML_STATUS_OK;
3551 }
3552
START_TEST(test_ext_entity_trailing_rsqb)3553 START_TEST(test_ext_entity_trailing_rsqb) {
3554 const char *text = "<!DOCTYPE doc [\n"
3555 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
3556 "]>\n"
3557 "<doc>&en;</doc>";
3558 int found_rsqb;
3559
3560 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3561 XML_SetExternalEntityRefHandler(g_parser, external_entity_rsqb_catcher);
3562 XML_SetUserData(g_parser, &found_rsqb);
3563 found_rsqb = 0;
3564 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3565 != XML_STATUS_OK)
3566 xml_failure(g_parser);
3567 if (found_rsqb == 0)
3568 fail("No right square bracket found");
3569 }
3570 END_TEST
3571
3572 /* Test CDATA handling in an external entity */
3573 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)3574 external_entity_good_cdata_ascii(XML_Parser parser, const XML_Char *context,
3575 const XML_Char *base, const XML_Char *systemId,
3576 const XML_Char *publicId) {
3577 const char *text = "<a><![CDATA[<greeting>Hello, world!</greeting>]]></a>";
3578 const XML_Char *expected = XCS("<greeting>Hello, world!</greeting>");
3579 CharData storage;
3580 XML_Parser ext_parser;
3581
3582 UNUSED_P(base);
3583 UNUSED_P(systemId);
3584 UNUSED_P(publicId);
3585 CharData_Init(&storage);
3586 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3587 if (ext_parser == NULL)
3588 fail("Could not create external entity parser");
3589 XML_SetUserData(ext_parser, &storage);
3590 XML_SetCharacterDataHandler(ext_parser, accumulate_characters);
3591
3592 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3593 == XML_STATUS_ERROR)
3594 xml_failure(ext_parser);
3595 CharData_CheckXMLChars(&storage, expected);
3596
3597 XML_ParserFree(ext_parser);
3598 return XML_STATUS_OK;
3599 }
3600
START_TEST(test_ext_entity_good_cdata)3601 START_TEST(test_ext_entity_good_cdata) {
3602 const char *text = "<!DOCTYPE doc [\n"
3603 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
3604 "]>\n"
3605 "<doc>&en;</doc>";
3606
3607 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3608 XML_SetExternalEntityRefHandler(g_parser, external_entity_good_cdata_ascii);
3609 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3610 != XML_STATUS_OK)
3611 xml_failure(g_parser);
3612 }
3613 END_TEST
3614
3615 /* Test user parameter settings */
3616 /* Variable holding the expected handler userData */
3617 static void *handler_data = NULL;
3618 /* Count of the number of times the comment handler has been invoked */
3619 static int comment_count = 0;
3620 /* Count of the number of skipped entities */
3621 static int skip_count = 0;
3622 /* Count of the number of times the XML declaration handler is invoked */
3623 static int xdecl_count = 0;
3624
3625 static void XMLCALL
xml_decl_handler(void * userData,const XML_Char * version,const XML_Char * encoding,int standalone)3626 xml_decl_handler(void *userData, const XML_Char *version,
3627 const XML_Char *encoding, int standalone) {
3628 UNUSED_P(version);
3629 UNUSED_P(encoding);
3630 if (userData != handler_data)
3631 fail("User data (xml decl) not correctly set");
3632 if (standalone != -1)
3633 fail("Standalone not flagged as not present in XML decl");
3634 xdecl_count++;
3635 }
3636
3637 static void XMLCALL
param_check_skip_handler(void * userData,const XML_Char * entityName,int is_parameter_entity)3638 param_check_skip_handler(void *userData, const XML_Char *entityName,
3639 int is_parameter_entity) {
3640 UNUSED_P(entityName);
3641 UNUSED_P(is_parameter_entity);
3642 if (userData != handler_data)
3643 fail("User data (skip) not correctly set");
3644 skip_count++;
3645 }
3646
3647 static void XMLCALL
data_check_comment_handler(void * userData,const XML_Char * data)3648 data_check_comment_handler(void *userData, const XML_Char *data) {
3649 UNUSED_P(data);
3650 /* Check that the userData passed through is what we expect */
3651 if (userData != handler_data)
3652 fail("User data (parser) not correctly set");
3653 /* Check that the user data in the parser is appropriate */
3654 if (XML_GetUserData(userData) != (void *)1)
3655 fail("User data in parser not correctly set");
3656 comment_count++;
3657 }
3658
3659 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)3660 external_entity_param_checker(XML_Parser parser, const XML_Char *context,
3661 const XML_Char *base, const XML_Char *systemId,
3662 const XML_Char *publicId) {
3663 const char *text = "<!-- Subordinate parser -->\n"
3664 "<!ELEMENT doc (#PCDATA)*>";
3665 XML_Parser ext_parser;
3666
3667 UNUSED_P(base);
3668 UNUSED_P(systemId);
3669 UNUSED_P(publicId);
3670 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3671 if (ext_parser == NULL)
3672 fail("Could not create external entity parser");
3673 handler_data = ext_parser;
3674 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3675 == XML_STATUS_ERROR) {
3676 xml_failure(parser);
3677 return XML_STATUS_ERROR;
3678 }
3679 handler_data = parser;
3680 XML_ParserFree(ext_parser);
3681 return XML_STATUS_OK;
3682 }
3683
START_TEST(test_user_parameters)3684 START_TEST(test_user_parameters) {
3685 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
3686 "<!-- Primary parse -->\n"
3687 "<!DOCTYPE doc SYSTEM 'foo'>\n"
3688 "<doc>&entity;";
3689 const char *epilog = "<!-- Back to primary parser -->\n"
3690 "</doc>";
3691
3692 comment_count = 0;
3693 skip_count = 0;
3694 xdecl_count = 0;
3695 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3696 XML_SetXmlDeclHandler(g_parser, xml_decl_handler);
3697 XML_SetExternalEntityRefHandler(g_parser, external_entity_param_checker);
3698 XML_SetCommentHandler(g_parser, data_check_comment_handler);
3699 XML_SetSkippedEntityHandler(g_parser, param_check_skip_handler);
3700 XML_UseParserAsHandlerArg(g_parser);
3701 XML_SetUserData(g_parser, (void *)1);
3702 handler_data = g_parser;
3703 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
3704 == XML_STATUS_ERROR)
3705 xml_failure(g_parser);
3706 if (comment_count != 2)
3707 fail("Comment handler not invoked enough times");
3708 /* Ensure we can't change policy mid-parse */
3709 if (XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_NEVER))
3710 fail("Changed param entity parsing policy while parsing");
3711 if (_XML_Parse_SINGLE_BYTES(g_parser, epilog, (int)strlen(epilog), XML_TRUE)
3712 == XML_STATUS_ERROR)
3713 xml_failure(g_parser);
3714 if (comment_count != 3)
3715 fail("Comment handler not invoked enough times");
3716 if (skip_count != 1)
3717 fail("Skip handler not invoked enough times");
3718 if (xdecl_count != 1)
3719 fail("XML declaration handler not invoked");
3720 }
3721 END_TEST
3722
3723 /* Test that an explicit external entity handler argument replaces
3724 * the parser as the first argument.
3725 *
3726 * We do not call the first parameter to the external entity handler
3727 * 'parser' for once, since the first time the handler is called it
3728 * will actually be a text string. We need to be able to access the
3729 * global 'parser' variable to create our external entity parser from,
3730 * since there are code paths we need to ensure get executed.
3731 */
3732 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)3733 external_entity_ref_param_checker(XML_Parser parameter, const XML_Char *context,
3734 const XML_Char *base,
3735 const XML_Char *systemId,
3736 const XML_Char *publicId) {
3737 const char *text = "<!ELEMENT doc (#PCDATA)*>";
3738 XML_Parser ext_parser;
3739
3740 UNUSED_P(base);
3741 UNUSED_P(systemId);
3742 UNUSED_P(publicId);
3743 if ((void *)parameter != handler_data)
3744 fail("External entity ref handler parameter not correct");
3745
3746 /* Here we use the global 'parser' variable */
3747 ext_parser = XML_ExternalEntityParserCreate(g_parser, context, NULL);
3748 if (ext_parser == NULL)
3749 fail("Could not create external entity parser");
3750 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3751 == XML_STATUS_ERROR)
3752 xml_failure(ext_parser);
3753
3754 XML_ParserFree(ext_parser);
3755 return XML_STATUS_OK;
3756 }
3757
START_TEST(test_ext_entity_ref_parameter)3758 START_TEST(test_ext_entity_ref_parameter) {
3759 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
3760 "<!DOCTYPE doc SYSTEM 'foo'>\n"
3761 "<doc>&entity;</doc>";
3762
3763 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3764 XML_SetExternalEntityRefHandler(g_parser, external_entity_ref_param_checker);
3765 /* Set a handler arg that is not NULL and not parser (which is
3766 * what NULL would cause to be passed.
3767 */
3768 XML_SetExternalEntityRefHandlerArg(g_parser, (void *)text);
3769 handler_data = (void *)text;
3770 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3771 == XML_STATUS_ERROR)
3772 xml_failure(g_parser);
3773
3774 /* Now try again with unset args */
3775 XML_ParserReset(g_parser, NULL);
3776 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3777 XML_SetExternalEntityRefHandler(g_parser, external_entity_ref_param_checker);
3778 XML_SetExternalEntityRefHandlerArg(g_parser, NULL);
3779 handler_data = (void *)g_parser;
3780 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3781 == XML_STATUS_ERROR)
3782 xml_failure(g_parser);
3783 }
3784 END_TEST
3785
3786 /* Test the parsing of an empty string */
START_TEST(test_empty_parse)3787 START_TEST(test_empty_parse) {
3788 const char *text = "<doc></doc>";
3789 const char *partial = "<doc>";
3790
3791 if (XML_Parse(g_parser, NULL, 0, XML_FALSE) == XML_STATUS_ERROR)
3792 fail("Parsing empty string faulted");
3793 if (XML_Parse(g_parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR)
3794 fail("Parsing final empty string not faulted");
3795 if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_ELEMENTS)
3796 fail("Parsing final empty string faulted for wrong reason");
3797
3798 /* Now try with valid text before the empty end */
3799 XML_ParserReset(g_parser, NULL);
3800 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
3801 == XML_STATUS_ERROR)
3802 xml_failure(g_parser);
3803 if (XML_Parse(g_parser, NULL, 0, XML_TRUE) == XML_STATUS_ERROR)
3804 fail("Parsing final empty string faulted");
3805
3806 /* Now try with invalid text before the empty end */
3807 XML_ParserReset(g_parser, NULL);
3808 if (_XML_Parse_SINGLE_BYTES(g_parser, partial, (int)strlen(partial),
3809 XML_FALSE)
3810 == XML_STATUS_ERROR)
3811 xml_failure(g_parser);
3812 if (XML_Parse(g_parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR)
3813 fail("Parsing final incomplete empty string not faulted");
3814 }
3815 END_TEST
3816
3817 /* Test odd corners of the XML_GetBuffer interface */
3818 static enum XML_Status
get_feature(enum XML_FeatureEnum feature_id,long * presult)3819 get_feature(enum XML_FeatureEnum feature_id, long *presult) {
3820 const XML_Feature *feature = XML_GetFeatureList();
3821
3822 if (feature == NULL)
3823 return XML_STATUS_ERROR;
3824 for (; feature->feature != XML_FEATURE_END; feature++) {
3825 if (feature->feature == feature_id) {
3826 *presult = feature->value;
3827 return XML_STATUS_OK;
3828 }
3829 }
3830 return XML_STATUS_ERROR;
3831 }
3832
3833 /* Having an element name longer than 1024 characters exercises some
3834 * of the pool allocation code in the parser that otherwise does not
3835 * get executed. The count at the end of the line is the number of
3836 * characters (bytes) in the element name by that point.x
3837 */
3838 static const char *get_buffer_test_text
3839 = "<documentwitharidiculouslylongelementnametotease" /* 0x030 */
3840 "aparticularcorneroftheallocationinXML_GetBuffers" /* 0x060 */
3841 "othatwecanimprovethecoverageyetagain012345678901" /* 0x090 */
3842 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x0c0 */
3843 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x0f0 */
3844 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x120 */
3845 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x150 */
3846 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x180 */
3847 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x1b0 */
3848 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x1e0 */
3849 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x210 */
3850 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x240 */
3851 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x270 */
3852 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x2a0 */
3853 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x2d0 */
3854 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x300 */
3855 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x330 */
3856 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x360 */
3857 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x390 */
3858 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x3c0 */
3859 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x3f0 */
3860 "123456789abcdef0123456789abcdef0123456789>\n<ef0"; /* 0x420 */
3861
3862 /* Test odd corners of the XML_GetBuffer interface */
START_TEST(test_get_buffer_1)3863 START_TEST(test_get_buffer_1) {
3864 const char *text = get_buffer_test_text;
3865 void *buffer;
3866 long context_bytes;
3867
3868 /* Attempt to allocate a negative length buffer */
3869 if (XML_GetBuffer(g_parser, -12) != NULL)
3870 fail("Negative length buffer not failed");
3871
3872 /* Now get a small buffer and extend it past valid length */
3873 buffer = XML_GetBuffer(g_parser, 1536);
3874 if (buffer == NULL)
3875 fail("1.5K buffer failed");
3876 assert(buffer != NULL);
3877 memcpy(buffer, text, strlen(text));
3878 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE)
3879 == XML_STATUS_ERROR)
3880 xml_failure(g_parser);
3881 if (XML_GetBuffer(g_parser, INT_MAX) != NULL)
3882 fail("INT_MAX buffer not failed");
3883
3884 /* Now try extending it a more reasonable but still too large
3885 * amount. The allocator in XML_GetBuffer() doubles the buffer
3886 * size until it exceeds the requested amount or INT_MAX. If it
3887 * exceeds INT_MAX, it rejects the request, so we want a request
3888 * between INT_MAX and INT_MAX/2. A gap of 1K seems comfortable,
3889 * with an extra byte just to ensure that the request is off any
3890 * boundary. The request will be inflated internally by
3891 * XML_CONTEXT_BYTES (if defined), so we subtract that from our
3892 * request.
3893 */
3894 if (get_feature(XML_FEATURE_CONTEXT_BYTES, &context_bytes) != XML_STATUS_OK)
3895 context_bytes = 0;
3896 if (XML_GetBuffer(g_parser, INT_MAX - (context_bytes + 1025)) != NULL)
3897 fail("INT_MAX- buffer not failed");
3898
3899 /* Now try extending it a carefully crafted amount */
3900 if (XML_GetBuffer(g_parser, 1000) == NULL)
3901 fail("1000 buffer failed");
3902 }
3903 END_TEST
3904
3905 /* Test more corners of the XML_GetBuffer interface */
START_TEST(test_get_buffer_2)3906 START_TEST(test_get_buffer_2) {
3907 const char *text = get_buffer_test_text;
3908 void *buffer;
3909
3910 /* Now get a decent buffer */
3911 buffer = XML_GetBuffer(g_parser, 1536);
3912 if (buffer == NULL)
3913 fail("1.5K buffer failed");
3914 assert(buffer != NULL);
3915 memcpy(buffer, text, strlen(text));
3916 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE)
3917 == XML_STATUS_ERROR)
3918 xml_failure(g_parser);
3919
3920 /* Extend it, to catch a different code path */
3921 if (XML_GetBuffer(g_parser, 1024) == NULL)
3922 fail("1024 buffer failed");
3923 }
3924 END_TEST
3925
3926 /* Test for signed integer overflow CVE-2022-23852 */
3927 #if defined(XML_CONTEXT_BYTES)
START_TEST(test_get_buffer_3_overflow)3928 START_TEST(test_get_buffer_3_overflow) {
3929 XML_Parser parser = XML_ParserCreate(NULL);
3930 assert(parser != NULL);
3931
3932 const char *const text = "\n";
3933 const int expectedKeepValue = (int)strlen(text);
3934
3935 // After this call, variable "keep" in XML_GetBuffer will
3936 // have value expectedKeepValue
3937 if (XML_Parse(parser, text, (int)strlen(text), XML_FALSE /* isFinal */)
3938 == XML_STATUS_ERROR)
3939 xml_failure(parser);
3940
3941 assert(expectedKeepValue > 0);
3942 if (XML_GetBuffer(parser, INT_MAX - expectedKeepValue + 1) != NULL)
3943 fail("enlarging buffer not failed");
3944
3945 XML_ParserFree(parser);
3946 }
3947 END_TEST
3948 #endif // defined(XML_CONTEXT_BYTES)
3949
3950 /* Test position information macros */
START_TEST(test_byte_info_at_end)3951 START_TEST(test_byte_info_at_end) {
3952 const char *text = "<doc></doc>";
3953
3954 if (XML_GetCurrentByteIndex(g_parser) != -1
3955 || XML_GetCurrentByteCount(g_parser) != 0)
3956 fail("Byte index/count incorrect at start of parse");
3957 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3958 == XML_STATUS_ERROR)
3959 xml_failure(g_parser);
3960 /* At end, the count will be zero and the index the end of string */
3961 if (XML_GetCurrentByteCount(g_parser) != 0)
3962 fail("Terminal byte count incorrect");
3963 if (XML_GetCurrentByteIndex(g_parser) != (XML_Index)strlen(text))
3964 fail("Terminal byte index incorrect");
3965 }
3966 END_TEST
3967
3968 /* Test position information from errors */
3969 #define PRE_ERROR_STR "<doc></"
3970 #define POST_ERROR_STR "wombat></doc>"
START_TEST(test_byte_info_at_error)3971 START_TEST(test_byte_info_at_error) {
3972 const char *text = PRE_ERROR_STR POST_ERROR_STR;
3973
3974 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3975 == XML_STATUS_OK)
3976 fail("Syntax error not faulted");
3977 if (XML_GetCurrentByteCount(g_parser) != 0)
3978 fail("Error byte count incorrect");
3979 if (XML_GetCurrentByteIndex(g_parser) != strlen(PRE_ERROR_STR))
3980 fail("Error byte index incorrect");
3981 }
3982 END_TEST
3983 #undef PRE_ERROR_STR
3984 #undef POST_ERROR_STR
3985
3986 /* Test position information in handler */
3987 typedef struct ByteTestData {
3988 int start_element_len;
3989 int cdata_len;
3990 int total_string_len;
3991 } ByteTestData;
3992
3993 static void
byte_character_handler(void * userData,const XML_Char * s,int len)3994 byte_character_handler(void *userData, const XML_Char *s, int len) {
3995 #ifdef XML_CONTEXT_BYTES
3996 int offset, size;
3997 const char *buffer;
3998 ByteTestData *data = (ByteTestData *)userData;
3999
4000 UNUSED_P(s);
4001 buffer = XML_GetInputContext(g_parser, &offset, &size);
4002 if (buffer == NULL)
4003 fail("Failed to get context buffer");
4004 if (offset != data->start_element_len)
4005 fail("Context offset in unexpected position");
4006 if (len != data->cdata_len)
4007 fail("CDATA length reported incorrectly");
4008 if (size != data->total_string_len)
4009 fail("Context size is not full buffer");
4010 if (XML_GetCurrentByteIndex(g_parser) != offset)
4011 fail("Character byte index incorrect");
4012 if (XML_GetCurrentByteCount(g_parser) != len)
4013 fail("Character byte count incorrect");
4014 #else
4015 UNUSED_P(s);
4016 UNUSED_P(userData);
4017 UNUSED_P(len);
4018 #endif
4019 }
4020
4021 #define START_ELEMENT "<e>"
4022 #define CDATA_TEXT "Hello"
4023 #define END_ELEMENT "</e>"
START_TEST(test_byte_info_at_cdata)4024 START_TEST(test_byte_info_at_cdata) {
4025 const char *text = START_ELEMENT CDATA_TEXT END_ELEMENT;
4026 int offset, size;
4027 ByteTestData data;
4028
4029 /* Check initial context is empty */
4030 if (XML_GetInputContext(g_parser, &offset, &size) != NULL)
4031 fail("Unexpected context at start of parse");
4032
4033 data.start_element_len = (int)strlen(START_ELEMENT);
4034 data.cdata_len = (int)strlen(CDATA_TEXT);
4035 data.total_string_len = (int)strlen(text);
4036 XML_SetCharacterDataHandler(g_parser, byte_character_handler);
4037 XML_SetUserData(g_parser, &data);
4038 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_OK)
4039 xml_failure(g_parser);
4040 }
4041 END_TEST
4042 #undef START_ELEMENT
4043 #undef CDATA_TEXT
4044 #undef END_ELEMENT
4045
4046 /* Test predefined entities are correctly recognised */
START_TEST(test_predefined_entities)4047 START_TEST(test_predefined_entities) {
4048 const char *text = "<doc><>&"'</doc>";
4049 const XML_Char *expected = XCS("<doc><>&"'</doc>");
4050 const XML_Char *result = XCS("<>&\"'");
4051 CharData storage;
4052
4053 XML_SetDefaultHandler(g_parser, accumulate_characters);
4054 /* run_character_check uses XML_SetCharacterDataHandler(), which
4055 * unfortunately heads off a code path that we need to exercise.
4056 */
4057 CharData_Init(&storage);
4058 XML_SetUserData(g_parser, &storage);
4059 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4060 == XML_STATUS_ERROR)
4061 xml_failure(g_parser);
4062 /* The default handler doesn't translate the entities */
4063 CharData_CheckXMLChars(&storage, expected);
4064
4065 /* Now try again and check the translation */
4066 XML_ParserReset(g_parser, NULL);
4067 run_character_check(text, result);
4068 }
4069 END_TEST
4070
4071 /* Regression test that an invalid tag in an external parameter
4072 * reference in an external DTD is correctly faulted.
4073 *
4074 * Only a few specific tags are legal in DTDs ignoring comments and
4075 * processing instructions, all of which begin with an exclamation
4076 * mark. "<el/>" is not one of them, so the parser should raise an
4077 * error on encountering it.
4078 */
4079 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)4080 external_entity_param(XML_Parser parser, const XML_Char *context,
4081 const XML_Char *base, const XML_Char *systemId,
4082 const XML_Char *publicId) {
4083 const char *text1 = "<!ELEMENT doc EMPTY>\n"
4084 "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
4085 "<!ENTITY % e2 '%e1;'>\n"
4086 "%e1;\n";
4087 const char *text2 = "<!ELEMENT el EMPTY>\n"
4088 "<el/>\n";
4089 XML_Parser ext_parser;
4090
4091 UNUSED_P(base);
4092 UNUSED_P(publicId);
4093 if (systemId == NULL)
4094 return XML_STATUS_OK;
4095
4096 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4097 if (ext_parser == NULL)
4098 fail("Could not create external entity parser");
4099
4100 if (! xcstrcmp(systemId, XCS("004-1.ent"))) {
4101 if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
4102 != XML_STATUS_ERROR)
4103 fail("Inner DTD with invalid tag not rejected");
4104 if (XML_GetErrorCode(ext_parser) != XML_ERROR_EXTERNAL_ENTITY_HANDLING)
4105 xml_failure(ext_parser);
4106 } else if (! xcstrcmp(systemId, XCS("004-2.ent"))) {
4107 if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE)
4108 != XML_STATUS_ERROR)
4109 fail("Invalid tag in external param not rejected");
4110 if (XML_GetErrorCode(ext_parser) != XML_ERROR_SYNTAX)
4111 xml_failure(ext_parser);
4112 } else {
4113 fail("Unknown system ID");
4114 }
4115
4116 XML_ParserFree(ext_parser);
4117 return XML_STATUS_ERROR;
4118 }
4119
START_TEST(test_invalid_tag_in_dtd)4120 START_TEST(test_invalid_tag_in_dtd) {
4121 const char *text = "<!DOCTYPE doc SYSTEM '004-1.ent'>\n"
4122 "<doc></doc>\n";
4123
4124 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4125 XML_SetExternalEntityRefHandler(g_parser, external_entity_param);
4126 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
4127 "Invalid tag IN DTD external param not rejected");
4128 }
4129 END_TEST
4130
4131 /* Test entities not quite the predefined ones are not mis-recognised */
START_TEST(test_not_predefined_entities)4132 START_TEST(test_not_predefined_entities) {
4133 const char *text[] = {"<doc>&pt;</doc>", "<doc>&amo;</doc>",
4134 "<doc>&quid;</doc>", "<doc>&apod;</doc>", NULL};
4135 int i = 0;
4136
4137 while (text[i] != NULL) {
4138 expect_failure(text[i], XML_ERROR_UNDEFINED_ENTITY,
4139 "Undefined entity not rejected");
4140 XML_ParserReset(g_parser, NULL);
4141 i++;
4142 }
4143 }
4144 END_TEST
4145
4146 /* Test conditional inclusion (IGNORE) */
4147 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)4148 external_entity_load_ignore(XML_Parser parser, const XML_Char *context,
4149 const XML_Char *base, const XML_Char *systemId,
4150 const XML_Char *publicId) {
4151 const char *text = "<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>";
4152 XML_Parser ext_parser;
4153
4154 UNUSED_P(base);
4155 UNUSED_P(systemId);
4156 UNUSED_P(publicId);
4157 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4158 if (ext_parser == NULL)
4159 fail("Could not create external entity parser");
4160 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
4161 == XML_STATUS_ERROR)
4162 xml_failure(parser);
4163
4164 XML_ParserFree(ext_parser);
4165 return XML_STATUS_OK;
4166 }
4167
START_TEST(test_ignore_section)4168 START_TEST(test_ignore_section) {
4169 const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
4170 "<doc><e>&entity;</e></doc>";
4171 const XML_Char *expected
4172 = XCS("<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>\n&entity;");
4173 CharData storage;
4174
4175 CharData_Init(&storage);
4176 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4177 XML_SetUserData(g_parser, &storage);
4178 XML_SetExternalEntityRefHandler(g_parser, external_entity_load_ignore);
4179 XML_SetDefaultHandler(g_parser, accumulate_characters);
4180 XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler);
4181 XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler);
4182 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4183 XML_SetStartElementHandler(g_parser, dummy_start_element);
4184 XML_SetEndElementHandler(g_parser, dummy_end_element);
4185 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4186 == XML_STATUS_ERROR)
4187 xml_failure(g_parser);
4188 CharData_CheckXMLChars(&storage, expected);
4189 }
4190 END_TEST
4191
4192 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)4193 external_entity_load_ignore_utf16(XML_Parser parser, const XML_Char *context,
4194 const XML_Char *base,
4195 const XML_Char *systemId,
4196 const XML_Char *publicId) {
4197 const char text[] =
4198 /* <![IGNORE[<!ELEMENT e (#PCDATA)*>]]> */
4199 "<\0!\0[\0I\0G\0N\0O\0R\0E\0[\0"
4200 "<\0!\0E\0L\0E\0M\0E\0N\0T\0 \0e\0 \0"
4201 "(\0#\0P\0C\0D\0A\0T\0A\0)\0*\0>\0]\0]\0>\0";
4202 XML_Parser ext_parser;
4203
4204 UNUSED_P(base);
4205 UNUSED_P(systemId);
4206 UNUSED_P(publicId);
4207 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4208 if (ext_parser == NULL)
4209 fail("Could not create external entity parser");
4210 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)sizeof(text) - 1, XML_TRUE)
4211 == XML_STATUS_ERROR)
4212 xml_failure(parser);
4213
4214 XML_ParserFree(ext_parser);
4215 return XML_STATUS_OK;
4216 }
4217
START_TEST(test_ignore_section_utf16)4218 START_TEST(test_ignore_section_utf16) {
4219 const char text[] =
4220 /* <!DOCTYPE d SYSTEM 's'> */
4221 "<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 "
4222 "\0S\0Y\0S\0T\0E\0M\0 \0'\0s\0'\0>\0\n\0"
4223 /* <d><e>&en;</e></d> */
4224 "<\0d\0>\0<\0e\0>\0&\0e\0n\0;\0<\0/\0e\0>\0<\0/\0d\0>\0";
4225 const XML_Char *expected = XCS("<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>\n&en;");
4226 CharData storage;
4227
4228 CharData_Init(&storage);
4229 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4230 XML_SetUserData(g_parser, &storage);
4231 XML_SetExternalEntityRefHandler(g_parser, external_entity_load_ignore_utf16);
4232 XML_SetDefaultHandler(g_parser, accumulate_characters);
4233 XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler);
4234 XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler);
4235 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4236 XML_SetStartElementHandler(g_parser, dummy_start_element);
4237 XML_SetEndElementHandler(g_parser, dummy_end_element);
4238 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
4239 == XML_STATUS_ERROR)
4240 xml_failure(g_parser);
4241 CharData_CheckXMLChars(&storage, expected);
4242 }
4243 END_TEST
4244
4245 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)4246 external_entity_load_ignore_utf16_be(XML_Parser parser, const XML_Char *context,
4247 const XML_Char *base,
4248 const XML_Char *systemId,
4249 const XML_Char *publicId) {
4250 const char text[] =
4251 /* <![IGNORE[<!ELEMENT e (#PCDATA)*>]]> */
4252 "\0<\0!\0[\0I\0G\0N\0O\0R\0E\0["
4253 "\0<\0!\0E\0L\0E\0M\0E\0N\0T\0 \0e\0 "
4254 "\0(\0#\0P\0C\0D\0A\0T\0A\0)\0*\0>\0]\0]\0>";
4255 XML_Parser ext_parser;
4256
4257 UNUSED_P(base);
4258 UNUSED_P(systemId);
4259 UNUSED_P(publicId);
4260 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4261 if (ext_parser == NULL)
4262 fail("Could not create external entity parser");
4263 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)sizeof(text) - 1, XML_TRUE)
4264 == XML_STATUS_ERROR)
4265 xml_failure(parser);
4266
4267 XML_ParserFree(ext_parser);
4268 return XML_STATUS_OK;
4269 }
4270
START_TEST(test_ignore_section_utf16_be)4271 START_TEST(test_ignore_section_utf16_be) {
4272 const char text[] =
4273 /* <!DOCTYPE d SYSTEM 's'> */
4274 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 "
4275 "\0S\0Y\0S\0T\0E\0M\0 \0'\0s\0'\0>\0\n"
4276 /* <d><e>&en;</e></d> */
4277 "\0<\0d\0>\0<\0e\0>\0&\0e\0n\0;\0<\0/\0e\0>\0<\0/\0d\0>";
4278 const XML_Char *expected = XCS("<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>\n&en;");
4279 CharData storage;
4280
4281 CharData_Init(&storage);
4282 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4283 XML_SetUserData(g_parser, &storage);
4284 XML_SetExternalEntityRefHandler(g_parser,
4285 external_entity_load_ignore_utf16_be);
4286 XML_SetDefaultHandler(g_parser, accumulate_characters);
4287 XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler);
4288 XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler);
4289 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4290 XML_SetStartElementHandler(g_parser, dummy_start_element);
4291 XML_SetEndElementHandler(g_parser, dummy_end_element);
4292 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
4293 == XML_STATUS_ERROR)
4294 xml_failure(g_parser);
4295 CharData_CheckXMLChars(&storage, expected);
4296 }
4297 END_TEST
4298
4299 /* Test mis-formatted conditional exclusion */
START_TEST(test_bad_ignore_section)4300 START_TEST(test_bad_ignore_section) {
4301 const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
4302 "<doc><e>&entity;</e></doc>";
4303 ExtFaults faults[]
4304 = {{"<![IGNORE[<!ELEM", "Broken-off declaration not faulted", NULL,
4305 XML_ERROR_SYNTAX},
4306 {"<![IGNORE[\x01]]>", "Invalid XML character not faulted", NULL,
4307 XML_ERROR_INVALID_TOKEN},
4308 {/* FIrst two bytes of a three-byte char */
4309 "<![IGNORE[\xe2\x82", "Partial XML character not faulted", NULL,
4310 XML_ERROR_PARTIAL_CHAR},
4311 {NULL, NULL, NULL, XML_ERROR_NONE}};
4312 ExtFaults *fault;
4313
4314 for (fault = &faults[0]; fault->parse_text != NULL; fault++) {
4315 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4316 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
4317 XML_SetUserData(g_parser, fault);
4318 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
4319 "Incomplete IGNORE section not failed");
4320 XML_ParserReset(g_parser, NULL);
4321 }
4322 }
4323 END_TEST
4324
4325 /* Test recursive parsing */
4326 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)4327 external_entity_valuer(XML_Parser parser, const XML_Char *context,
4328 const XML_Char *base, const XML_Char *systemId,
4329 const XML_Char *publicId) {
4330 const char *text1 = "<!ELEMENT doc EMPTY>\n"
4331 "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
4332 "<!ENTITY % e2 '%e1;'>\n"
4333 "%e1;\n";
4334 XML_Parser ext_parser;
4335
4336 UNUSED_P(base);
4337 UNUSED_P(publicId);
4338 if (systemId == NULL)
4339 return XML_STATUS_OK;
4340 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4341 if (ext_parser == NULL)
4342 fail("Could not create external entity parser");
4343 if (! xcstrcmp(systemId, XCS("004-1.ent"))) {
4344 if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
4345 == XML_STATUS_ERROR)
4346 xml_failure(ext_parser);
4347 } else if (! xcstrcmp(systemId, XCS("004-2.ent"))) {
4348 ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser);
4349 enum XML_Status status;
4350 enum XML_Error error;
4351
4352 status = _XML_Parse_SINGLE_BYTES(ext_parser, fault->parse_text,
4353 (int)strlen(fault->parse_text), XML_TRUE);
4354 if (fault->error == XML_ERROR_NONE) {
4355 if (status == XML_STATUS_ERROR)
4356 xml_failure(ext_parser);
4357 } else {
4358 if (status != XML_STATUS_ERROR)
4359 fail(fault->fail_text);
4360 error = XML_GetErrorCode(ext_parser);
4361 if (error != fault->error
4362 && (fault->error != XML_ERROR_XML_DECL
4363 || error != XML_ERROR_TEXT_DECL))
4364 xml_failure(ext_parser);
4365 }
4366 }
4367
4368 XML_ParserFree(ext_parser);
4369 return XML_STATUS_OK;
4370 }
4371
START_TEST(test_external_entity_values)4372 START_TEST(test_external_entity_values) {
4373 const char *text = "<!DOCTYPE doc SYSTEM '004-1.ent'>\n"
4374 "<doc></doc>\n";
4375 ExtFaults data_004_2[] = {
4376 {"<!ATTLIST doc a1 CDATA 'value'>", NULL, NULL, XML_ERROR_NONE},
4377 {"<!ATTLIST $doc a1 CDATA 'value'>", "Invalid token not faulted", NULL,
4378 XML_ERROR_INVALID_TOKEN},
4379 {"'wombat", "Unterminated string not faulted", NULL,
4380 XML_ERROR_UNCLOSED_TOKEN},
4381 {"\xe2\x82", "Partial UTF-8 character not faulted", NULL,
4382 XML_ERROR_PARTIAL_CHAR},
4383 {"<?xml version='1.0' encoding='utf-8'?>\n", NULL, NULL, XML_ERROR_NONE},
4384 {"<?xml?>", "Malformed XML declaration not faulted", NULL,
4385 XML_ERROR_XML_DECL},
4386 {/* UTF-8 BOM */
4387 "\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>", NULL, NULL,
4388 XML_ERROR_NONE},
4389 {"<?xml version='1.0' encoding='utf-8'?>\n$",
4390 "Invalid token after text declaration not faulted", NULL,
4391 XML_ERROR_INVALID_TOKEN},
4392 {"<?xml version='1.0' encoding='utf-8'?>\n'wombat",
4393 "Unterminated string after text decl not faulted", NULL,
4394 XML_ERROR_UNCLOSED_TOKEN},
4395 {"<?xml version='1.0' encoding='utf-8'?>\n\xe2\x82",
4396 "Partial UTF-8 character after text decl not faulted", NULL,
4397 XML_ERROR_PARTIAL_CHAR},
4398 {"%e1;", "Recursive parameter entity not faulted", NULL,
4399 XML_ERROR_RECURSIVE_ENTITY_REF},
4400 {NULL, NULL, NULL, XML_ERROR_NONE}};
4401 int i;
4402
4403 for (i = 0; data_004_2[i].parse_text != NULL; i++) {
4404 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4405 XML_SetExternalEntityRefHandler(g_parser, external_entity_valuer);
4406 XML_SetUserData(g_parser, &data_004_2[i]);
4407 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4408 == XML_STATUS_ERROR)
4409 xml_failure(g_parser);
4410 XML_ParserReset(g_parser, NULL);
4411 }
4412 }
4413 END_TEST
4414
4415 /* Test the recursive parse interacts with a not standalone handler */
4416 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)4417 external_entity_not_standalone(XML_Parser parser, const XML_Char *context,
4418 const XML_Char *base, const XML_Char *systemId,
4419 const XML_Char *publicId) {
4420 const char *text1 = "<!ELEMENT doc EMPTY>\n"
4421 "<!ENTITY % e1 SYSTEM 'bar'>\n"
4422 "%e1;\n";
4423 const char *text2 = "<!ATTLIST doc a1 CDATA 'value'>";
4424 XML_Parser ext_parser;
4425
4426 UNUSED_P(base);
4427 UNUSED_P(publicId);
4428 if (systemId == NULL)
4429 return XML_STATUS_OK;
4430 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4431 if (ext_parser == NULL)
4432 fail("Could not create external entity parser");
4433 if (! xcstrcmp(systemId, XCS("foo"))) {
4434 XML_SetNotStandaloneHandler(ext_parser, reject_not_standalone_handler);
4435 if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
4436 != XML_STATUS_ERROR)
4437 fail("Expected not standalone rejection");
4438 if (XML_GetErrorCode(ext_parser) != XML_ERROR_NOT_STANDALONE)
4439 xml_failure(ext_parser);
4440 XML_SetNotStandaloneHandler(ext_parser, NULL);
4441 XML_ParserFree(ext_parser);
4442 return XML_STATUS_ERROR;
4443 } else if (! xcstrcmp(systemId, XCS("bar"))) {
4444 if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE)
4445 == XML_STATUS_ERROR)
4446 xml_failure(ext_parser);
4447 }
4448
4449 XML_ParserFree(ext_parser);
4450 return XML_STATUS_OK;
4451 }
4452
START_TEST(test_ext_entity_not_standalone)4453 START_TEST(test_ext_entity_not_standalone) {
4454 const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
4455 "<doc></doc>";
4456
4457 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4458 XML_SetExternalEntityRefHandler(g_parser, external_entity_not_standalone);
4459 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
4460 "Standalone rejection not caught");
4461 }
4462 END_TEST
4463
4464 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)4465 external_entity_value_aborter(XML_Parser parser, const XML_Char *context,
4466 const XML_Char *base, const XML_Char *systemId,
4467 const XML_Char *publicId) {
4468 const char *text1 = "<!ELEMENT doc EMPTY>\n"
4469 "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
4470 "<!ENTITY % e2 '%e1;'>\n"
4471 "%e1;\n";
4472 const char *text2 = "<?xml version='1.0' encoding='utf-8'?>";
4473 XML_Parser ext_parser;
4474
4475 UNUSED_P(base);
4476 UNUSED_P(publicId);
4477 if (systemId == NULL)
4478 return XML_STATUS_OK;
4479 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4480 if (ext_parser == NULL)
4481 fail("Could not create external entity parser");
4482 if (! xcstrcmp(systemId, XCS("004-1.ent"))) {
4483 if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
4484 == XML_STATUS_ERROR)
4485 xml_failure(ext_parser);
4486 }
4487 if (! xcstrcmp(systemId, XCS("004-2.ent"))) {
4488 XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
4489 XML_SetUserData(ext_parser, ext_parser);
4490 if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE)
4491 != XML_STATUS_ERROR)
4492 fail("Aborted parse not faulted");
4493 if (XML_GetErrorCode(ext_parser) != XML_ERROR_ABORTED)
4494 xml_failure(ext_parser);
4495 }
4496
4497 XML_ParserFree(ext_parser);
4498 return XML_STATUS_OK;
4499 }
4500
START_TEST(test_ext_entity_value_abort)4501 START_TEST(test_ext_entity_value_abort) {
4502 const char *text = "<!DOCTYPE doc SYSTEM '004-1.ent'>\n"
4503 "<doc></doc>\n";
4504
4505 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4506 XML_SetExternalEntityRefHandler(g_parser, external_entity_value_aborter);
4507 resumable = XML_FALSE;
4508 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4509 == XML_STATUS_ERROR)
4510 xml_failure(g_parser);
4511 }
4512 END_TEST
4513
START_TEST(test_bad_public_doctype)4514 START_TEST(test_bad_public_doctype) {
4515 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
4516 "<!DOCTYPE doc PUBLIC '{BadName}' 'test'>\n"
4517 "<doc></doc>";
4518
4519 /* Setting a handler provokes a particular code path */
4520 XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_handler,
4521 dummy_end_doctype_handler);
4522 expect_failure(text, XML_ERROR_PUBLICID, "Bad Public ID not failed");
4523 }
4524 END_TEST
4525
4526 /* Test based on ibm/valid/P32/ibm32v04.xml */
START_TEST(test_attribute_enum_value)4527 START_TEST(test_attribute_enum_value) {
4528 const char *text = "<?xml version='1.0' standalone='no'?>\n"
4529 "<!DOCTYPE animal SYSTEM 'test.dtd'>\n"
4530 "<animal>This is a \n <a/> \n\nyellow tiger</animal>";
4531 ExtTest dtd_data
4532 = {"<!ELEMENT animal (#PCDATA|a)*>\n"
4533 "<!ELEMENT a EMPTY>\n"
4534 "<!ATTLIST animal xml:space (default|preserve) 'preserve'>",
4535 NULL, NULL};
4536 const XML_Char *expected = XCS("This is a \n \n\nyellow tiger");
4537
4538 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
4539 XML_SetUserData(g_parser, &dtd_data);
4540 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4541 /* An attribute list handler provokes a different code path */
4542 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
4543 run_ext_character_check(text, &dtd_data, expected);
4544 }
4545 END_TEST
4546
4547 /* Slightly bizarrely, the library seems to silently ignore entity
4548 * definitions for predefined entities, even when they are wrong. The
4549 * language of the XML 1.0 spec is somewhat unhelpful as to what ought
4550 * to happen, so this is currently treated as acceptable.
4551 */
START_TEST(test_predefined_entity_redefinition)4552 START_TEST(test_predefined_entity_redefinition) {
4553 const char *text = "<!DOCTYPE doc [\n"
4554 "<!ENTITY apos 'foo'>\n"
4555 "]>\n"
4556 "<doc>'</doc>";
4557 run_character_check(text, XCS("'"));
4558 }
4559 END_TEST
4560
4561 /* Test that the parser stops processing the DTD after an unresolved
4562 * parameter entity is encountered.
4563 */
START_TEST(test_dtd_stop_processing)4564 START_TEST(test_dtd_stop_processing) {
4565 const char *text = "<!DOCTYPE doc [\n"
4566 "%foo;\n"
4567 "<!ENTITY bar 'bas'>\n"
4568 "]><doc/>";
4569
4570 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
4571 dummy_handler_flags = 0;
4572 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4573 == XML_STATUS_ERROR)
4574 xml_failure(g_parser);
4575 if (dummy_handler_flags != 0)
4576 fail("DTD processing still going after undefined PE");
4577 }
4578 END_TEST
4579
4580 /* Test public notations with no system ID */
START_TEST(test_public_notation_no_sysid)4581 START_TEST(test_public_notation_no_sysid) {
4582 const char *text = "<!DOCTYPE doc [\n"
4583 "<!NOTATION note PUBLIC 'foo'>\n"
4584 "<!ELEMENT doc EMPTY>\n"
4585 "]>\n<doc/>";
4586
4587 dummy_handler_flags = 0;
4588 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
4589 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4590 == XML_STATUS_ERROR)
4591 xml_failure(g_parser);
4592 if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG)
4593 fail("Notation declaration handler not called");
4594 }
4595 END_TEST
4596
4597 static void XMLCALL
record_element_start_handler(void * userData,const XML_Char * name,const XML_Char ** atts)4598 record_element_start_handler(void *userData, const XML_Char *name,
4599 const XML_Char **atts) {
4600 UNUSED_P(atts);
4601 CharData_AppendXMLChars((CharData *)userData, name, (int)xcstrlen(name));
4602 }
4603
START_TEST(test_nested_groups)4604 START_TEST(test_nested_groups) {
4605 const char *text
4606 = "<!DOCTYPE doc [\n"
4607 "<!ELEMENT doc "
4608 /* Sixteen elements per line */
4609 "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,"
4610 "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?"
4611 "))))))))))))))))))))))))))))))))>\n"
4612 "<!ELEMENT e EMPTY>"
4613 "]>\n"
4614 "<doc><e/></doc>";
4615 CharData storage;
4616
4617 CharData_Init(&storage);
4618 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4619 XML_SetStartElementHandler(g_parser, record_element_start_handler);
4620 XML_SetUserData(g_parser, &storage);
4621 dummy_handler_flags = 0;
4622 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4623 == XML_STATUS_ERROR)
4624 xml_failure(g_parser);
4625 CharData_CheckXMLChars(&storage, XCS("doce"));
4626 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
4627 fail("Element handler not fired");
4628 }
4629 END_TEST
4630
START_TEST(test_group_choice)4631 START_TEST(test_group_choice) {
4632 const char *text = "<!DOCTYPE doc [\n"
4633 "<!ELEMENT doc (a|b|c)+>\n"
4634 "<!ELEMENT a EMPTY>\n"
4635 "<!ELEMENT b (#PCDATA)>\n"
4636 "<!ELEMENT c ANY>\n"
4637 "]>\n"
4638 "<doc>\n"
4639 "<a/>\n"
4640 "<b attr='foo'>This is a foo</b>\n"
4641 "<c></c>\n"
4642 "</doc>\n";
4643
4644 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4645 dummy_handler_flags = 0;
4646 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4647 == XML_STATUS_ERROR)
4648 xml_failure(g_parser);
4649 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
4650 fail("Element handler flag not raised");
4651 }
4652 END_TEST
4653
4654 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)4655 external_entity_public(XML_Parser parser, const XML_Char *context,
4656 const XML_Char *base, const XML_Char *systemId,
4657 const XML_Char *publicId) {
4658 const char *text1 = (const char *)XML_GetUserData(parser);
4659 const char *text2 = "<!ATTLIST doc a CDATA 'value'>";
4660 const char *text = NULL;
4661 XML_Parser ext_parser;
4662 int parse_res;
4663
4664 UNUSED_P(base);
4665 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4666 if (ext_parser == NULL)
4667 return XML_STATUS_ERROR;
4668 if (systemId != NULL && ! xcstrcmp(systemId, XCS("http://example.org/"))) {
4669 text = text1;
4670 } else if (publicId != NULL && ! xcstrcmp(publicId, XCS("foo"))) {
4671 text = text2;
4672 } else
4673 fail("Unexpected parameters to external entity parser");
4674 assert(text != NULL);
4675 parse_res
4676 = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
4677 XML_ParserFree(ext_parser);
4678 return parse_res;
4679 }
4680
START_TEST(test_standalone_parameter_entity)4681 START_TEST(test_standalone_parameter_entity) {
4682 const char *text = "<?xml version='1.0' standalone='yes'?>\n"
4683 "<!DOCTYPE doc SYSTEM 'http://example.org/' [\n"
4684 "<!ENTITY % entity '<!ELEMENT doc (#PCDATA)>'>\n"
4685 "%entity;\n"
4686 "]>\n"
4687 "<doc></doc>";
4688 char dtd_data[] = "<!ENTITY % e1 'foo'>\n";
4689
4690 XML_SetUserData(g_parser, dtd_data);
4691 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4692 XML_SetExternalEntityRefHandler(g_parser, external_entity_public);
4693 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4694 == XML_STATUS_ERROR)
4695 xml_failure(g_parser);
4696 }
4697 END_TEST
4698
4699 /* Test skipping of parameter entity in an external DTD */
4700 /* Derived from ibm/invalid/P69/ibm69i01.xml */
START_TEST(test_skipped_parameter_entity)4701 START_TEST(test_skipped_parameter_entity) {
4702 const char *text = "<?xml version='1.0'?>\n"
4703 "<!DOCTYPE root SYSTEM 'http://example.org/dtd.ent' [\n"
4704 "<!ELEMENT root (#PCDATA|a)* >\n"
4705 "]>\n"
4706 "<root></root>";
4707 ExtTest dtd_data = {"%pe2;", NULL, NULL};
4708
4709 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
4710 XML_SetUserData(g_parser, &dtd_data);
4711 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4712 XML_SetSkippedEntityHandler(g_parser, dummy_skip_handler);
4713 dummy_handler_flags = 0;
4714 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4715 == XML_STATUS_ERROR)
4716 xml_failure(g_parser);
4717 if (dummy_handler_flags != DUMMY_SKIP_HANDLER_FLAG)
4718 fail("Skip handler not executed");
4719 }
4720 END_TEST
4721
4722 /* Test recursive parameter entity definition rejected in external DTD */
START_TEST(test_recursive_external_parameter_entity)4723 START_TEST(test_recursive_external_parameter_entity) {
4724 const char *text = "<?xml version='1.0'?>\n"
4725 "<!DOCTYPE root SYSTEM 'http://example.org/dtd.ent' [\n"
4726 "<!ELEMENT root (#PCDATA|a)* >\n"
4727 "]>\n"
4728 "<root></root>";
4729 ExtFaults dtd_data = {"<!ENTITY % pe2 '%pe2;'>\n%pe2;",
4730 "Recursive external parameter entity not faulted", NULL,
4731 XML_ERROR_RECURSIVE_ENTITY_REF};
4732
4733 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
4734 XML_SetUserData(g_parser, &dtd_data);
4735 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4736 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
4737 "Recursive external parameter not spotted");
4738 }
4739 END_TEST
4740
4741 /* Test undefined parameter entity in external entity handler */
4742 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)4743 external_entity_devaluer(XML_Parser parser, const XML_Char *context,
4744 const XML_Char *base, const XML_Char *systemId,
4745 const XML_Char *publicId) {
4746 const char *text = "<!ELEMENT doc EMPTY>\n"
4747 "<!ENTITY % e1 SYSTEM 'bar'>\n"
4748 "%e1;\n";
4749 XML_Parser ext_parser;
4750 intptr_t clear_handler = (intptr_t)XML_GetUserData(parser);
4751
4752 UNUSED_P(base);
4753 UNUSED_P(publicId);
4754 if (systemId == NULL || ! xcstrcmp(systemId, XCS("bar")))
4755 return XML_STATUS_OK;
4756 if (xcstrcmp(systemId, XCS("foo")))
4757 fail("Unexpected system ID");
4758 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4759 if (ext_parser == NULL)
4760 fail("Could note create external entity parser");
4761 if (clear_handler)
4762 XML_SetExternalEntityRefHandler(ext_parser, NULL);
4763 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
4764 == XML_STATUS_ERROR)
4765 xml_failure(ext_parser);
4766
4767 XML_ParserFree(ext_parser);
4768 return XML_STATUS_OK;
4769 }
4770
START_TEST(test_undefined_ext_entity_in_external_dtd)4771 START_TEST(test_undefined_ext_entity_in_external_dtd) {
4772 const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
4773 "<doc></doc>\n";
4774
4775 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4776 XML_SetExternalEntityRefHandler(g_parser, external_entity_devaluer);
4777 XML_SetUserData(g_parser, (void *)(intptr_t)XML_FALSE);
4778 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4779 == XML_STATUS_ERROR)
4780 xml_failure(g_parser);
4781
4782 /* Now repeat without the external entity ref handler invoking
4783 * another copy of itself.
4784 */
4785 XML_ParserReset(g_parser, NULL);
4786 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4787 XML_SetExternalEntityRefHandler(g_parser, external_entity_devaluer);
4788 XML_SetUserData(g_parser, (void *)(intptr_t)XML_TRUE);
4789 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4790 == XML_STATUS_ERROR)
4791 xml_failure(g_parser);
4792 }
4793 END_TEST
4794
4795 static void XMLCALL
aborting_xdecl_handler(void * userData,const XML_Char * version,const XML_Char * encoding,int standalone)4796 aborting_xdecl_handler(void *userData, const XML_Char *version,
4797 const XML_Char *encoding, int standalone) {
4798 UNUSED_P(userData);
4799 UNUSED_P(version);
4800 UNUSED_P(encoding);
4801 UNUSED_P(standalone);
4802 XML_StopParser(g_parser, resumable);
4803 XML_SetXmlDeclHandler(g_parser, NULL);
4804 }
4805
4806 /* Test suspending the parse on receiving an XML declaration works */
START_TEST(test_suspend_xdecl)4807 START_TEST(test_suspend_xdecl) {
4808 const char *text = long_character_data_text;
4809
4810 XML_SetXmlDeclHandler(g_parser, aborting_xdecl_handler);
4811 resumable = XML_TRUE;
4812 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4813 != XML_STATUS_SUSPENDED)
4814 xml_failure(g_parser);
4815 if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE)
4816 xml_failure(g_parser);
4817 /* Attempt to start a new parse while suspended */
4818 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
4819 != XML_STATUS_ERROR)
4820 fail("Attempt to parse while suspended not faulted");
4821 if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED)
4822 fail("Suspended parse not faulted with correct error");
4823 }
4824 END_TEST
4825
4826 /* Test aborting the parse in an epilog works */
4827 static void XMLCALL
selective_aborting_default_handler(void * userData,const XML_Char * s,int len)4828 selective_aborting_default_handler(void *userData, const XML_Char *s, int len) {
4829 const XML_Char *match = (const XML_Char *)userData;
4830
4831 if (match == NULL
4832 || (xcstrlen(match) == (unsigned)len && ! xcstrncmp(match, s, len))) {
4833 XML_StopParser(g_parser, resumable);
4834 XML_SetDefaultHandler(g_parser, NULL);
4835 }
4836 }
4837
START_TEST(test_abort_epilog)4838 START_TEST(test_abort_epilog) {
4839 const char *text = "<doc></doc>\n\r\n";
4840 XML_Char match[] = XCS("\r");
4841
4842 XML_SetDefaultHandler(g_parser, selective_aborting_default_handler);
4843 XML_SetUserData(g_parser, match);
4844 resumable = XML_FALSE;
4845 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4846 != XML_STATUS_ERROR)
4847 fail("Abort not triggered");
4848 if (XML_GetErrorCode(g_parser) != XML_ERROR_ABORTED)
4849 xml_failure(g_parser);
4850 }
4851 END_TEST
4852
4853 /* Test a different code path for abort in the epilog */
START_TEST(test_abort_epilog_2)4854 START_TEST(test_abort_epilog_2) {
4855 const char *text = "<doc></doc>\n";
4856 XML_Char match[] = XCS("\n");
4857
4858 XML_SetDefaultHandler(g_parser, selective_aborting_default_handler);
4859 XML_SetUserData(g_parser, match);
4860 resumable = XML_FALSE;
4861 expect_failure(text, XML_ERROR_ABORTED, "Abort not triggered");
4862 }
4863 END_TEST
4864
4865 /* Test suspension from the epilog */
START_TEST(test_suspend_epilog)4866 START_TEST(test_suspend_epilog) {
4867 const char *text = "<doc></doc>\n";
4868 XML_Char match[] = XCS("\n");
4869
4870 XML_SetDefaultHandler(g_parser, selective_aborting_default_handler);
4871 XML_SetUserData(g_parser, match);
4872 resumable = XML_TRUE;
4873 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4874 != XML_STATUS_SUSPENDED)
4875 xml_failure(g_parser);
4876 }
4877 END_TEST
4878
4879 static void XMLCALL
suspending_end_handler(void * userData,const XML_Char * s)4880 suspending_end_handler(void *userData, const XML_Char *s) {
4881 UNUSED_P(s);
4882 XML_StopParser((XML_Parser)userData, 1);
4883 }
4884
START_TEST(test_suspend_in_sole_empty_tag)4885 START_TEST(test_suspend_in_sole_empty_tag) {
4886 const char *text = "<doc/>";
4887 enum XML_Status rc;
4888
4889 XML_SetEndElementHandler(g_parser, suspending_end_handler);
4890 XML_SetUserData(g_parser, g_parser);
4891 rc = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE);
4892 if (rc == XML_STATUS_ERROR)
4893 xml_failure(g_parser);
4894 else if (rc != XML_STATUS_SUSPENDED)
4895 fail("Suspend not triggered");
4896 rc = XML_ResumeParser(g_parser);
4897 if (rc == XML_STATUS_ERROR)
4898 xml_failure(g_parser);
4899 else if (rc != XML_STATUS_OK)
4900 fail("Resume failed");
4901 }
4902 END_TEST
4903
START_TEST(test_unfinished_epilog)4904 START_TEST(test_unfinished_epilog) {
4905 const char *text = "<doc></doc><";
4906
4907 expect_failure(text, XML_ERROR_UNCLOSED_TOKEN,
4908 "Incomplete epilog entry not faulted");
4909 }
4910 END_TEST
4911
START_TEST(test_partial_char_in_epilog)4912 START_TEST(test_partial_char_in_epilog) {
4913 const char *text = "<doc></doc>\xe2\x82";
4914
4915 /* First check that no fault is raised if the parse is not finished */
4916 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
4917 == XML_STATUS_ERROR)
4918 xml_failure(g_parser);
4919 /* Now check that it is faulted once we finish */
4920 if (XML_ParseBuffer(g_parser, 0, XML_TRUE) != XML_STATUS_ERROR)
4921 fail("Partial character in epilog not faulted");
4922 if (XML_GetErrorCode(g_parser) != XML_ERROR_PARTIAL_CHAR)
4923 xml_failure(g_parser);
4924 }
4925 END_TEST
4926
START_TEST(test_hash_collision)4927 START_TEST(test_hash_collision) {
4928 /* For full coverage of the lookup routine, we need to ensure a
4929 * hash collision even though we can only tell that we have one
4930 * through breakpoint debugging or coverage statistics. The
4931 * following will cause a hash collision on machines with a 64-bit
4932 * long type; others will have to experiment. The full coverage
4933 * tests invoked from qa.sh usually provide a hash collision, but
4934 * not always. This is an attempt to provide insurance.
4935 */
4936 #define COLLIDING_HASH_SALT (unsigned long)_SIP_ULL(0xffffffffU, 0xff99fc90U)
4937 const char *text
4938 = "<doc>\n"
4939 "<a1/><a2/><a3/><a4/><a5/><a6/><a7/><a8/>\n"
4940 "<b1></b1><b2 attr='foo'>This is a foo</b2><b3></b3><b4></b4>\n"
4941 "<b5></b5><b6></b6><b7></b7><b8></b8>\n"
4942 "<c1/><c2/><c3/><c4/><c5/><c6/><c7/><c8/>\n"
4943 "<d1/><d2/><d3/><d4/><d5/><d6/><d7/>\n"
4944 "<d8>This triggers the table growth and collides with b2</d8>\n"
4945 "</doc>\n";
4946
4947 XML_SetHashSalt(g_parser, COLLIDING_HASH_SALT);
4948 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4949 == XML_STATUS_ERROR)
4950 xml_failure(g_parser);
4951 }
4952 END_TEST
4953 #undef COLLIDING_HASH_SALT
4954
4955 /* Test resuming a parse suspended in entity substitution */
4956 static void XMLCALL
start_element_suspender(void * userData,const XML_Char * name,const XML_Char ** atts)4957 start_element_suspender(void *userData, const XML_Char *name,
4958 const XML_Char **atts) {
4959 UNUSED_P(userData);
4960 UNUSED_P(atts);
4961 if (! xcstrcmp(name, XCS("suspend")))
4962 XML_StopParser(g_parser, XML_TRUE);
4963 if (! xcstrcmp(name, XCS("abort")))
4964 XML_StopParser(g_parser, XML_FALSE);
4965 }
4966
START_TEST(test_suspend_resume_internal_entity)4967 START_TEST(test_suspend_resume_internal_entity) {
4968 const char *text
4969 = "<!DOCTYPE doc [\n"
4970 "<!ENTITY foo '<suspend>Hi<suspend>Ho</suspend></suspend>'>\n"
4971 "]>\n"
4972 "<doc>&foo;</doc>\n";
4973 const XML_Char *expected1 = XCS("Hi");
4974 const XML_Char *expected2 = XCS("HiHo");
4975 CharData storage;
4976
4977 CharData_Init(&storage);
4978 XML_SetStartElementHandler(g_parser, start_element_suspender);
4979 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
4980 XML_SetUserData(g_parser, &storage);
4981 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
4982 != XML_STATUS_SUSPENDED)
4983 xml_failure(g_parser);
4984 CharData_CheckXMLChars(&storage, XCS(""));
4985 if (XML_ResumeParser(g_parser) != XML_STATUS_SUSPENDED)
4986 xml_failure(g_parser);
4987 CharData_CheckXMLChars(&storage, expected1);
4988 if (XML_ResumeParser(g_parser) != XML_STATUS_OK)
4989 xml_failure(g_parser);
4990 CharData_CheckXMLChars(&storage, expected2);
4991 }
4992 END_TEST
4993
4994 /* Test syntax error is caught at parse resumption */
START_TEST(test_resume_entity_with_syntax_error)4995 START_TEST(test_resume_entity_with_syntax_error) {
4996 const char *text = "<!DOCTYPE doc [\n"
4997 "<!ENTITY foo '<suspend>Hi</wombat>'>\n"
4998 "]>\n"
4999 "<doc>&foo;</doc>\n";
5000
5001 XML_SetStartElementHandler(g_parser, start_element_suspender);
5002 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
5003 != XML_STATUS_SUSPENDED)
5004 xml_failure(g_parser);
5005 if (XML_ResumeParser(g_parser) != XML_STATUS_ERROR)
5006 fail("Syntax error in entity not faulted");
5007 if (XML_GetErrorCode(g_parser) != XML_ERROR_TAG_MISMATCH)
5008 xml_failure(g_parser);
5009 }
5010 END_TEST
5011
5012 /* Test suspending and resuming in a parameter entity substitution */
5013 static void XMLCALL
element_decl_suspender(void * userData,const XML_Char * name,XML_Content * model)5014 element_decl_suspender(void *userData, const XML_Char *name,
5015 XML_Content *model) {
5016 UNUSED_P(userData);
5017 UNUSED_P(name);
5018 XML_StopParser(g_parser, XML_TRUE);
5019 XML_FreeContentModel(g_parser, model);
5020 }
5021
START_TEST(test_suspend_resume_parameter_entity)5022 START_TEST(test_suspend_resume_parameter_entity) {
5023 const char *text = "<!DOCTYPE doc [\n"
5024 "<!ENTITY % foo '<!ELEMENT doc (#PCDATA)*>'>\n"
5025 "%foo;\n"
5026 "]>\n"
5027 "<doc>Hello, world</doc>";
5028 const XML_Char *expected = XCS("Hello, world");
5029 CharData storage;
5030
5031 CharData_Init(&storage);
5032 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5033 XML_SetElementDeclHandler(g_parser, element_decl_suspender);
5034 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
5035 XML_SetUserData(g_parser, &storage);
5036 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
5037 != XML_STATUS_SUSPENDED)
5038 xml_failure(g_parser);
5039 CharData_CheckXMLChars(&storage, XCS(""));
5040 if (XML_ResumeParser(g_parser) != XML_STATUS_OK)
5041 xml_failure(g_parser);
5042 CharData_CheckXMLChars(&storage, expected);
5043 }
5044 END_TEST
5045
5046 /* Test attempting to use parser after an error is faulted */
START_TEST(test_restart_on_error)5047 START_TEST(test_restart_on_error) {
5048 const char *text = "<$doc><doc></doc>";
5049
5050 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
5051 != XML_STATUS_ERROR)
5052 fail("Invalid tag name not faulted");
5053 if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
5054 xml_failure(g_parser);
5055 if (XML_Parse(g_parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR)
5056 fail("Restarting invalid parse not faulted");
5057 if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
5058 xml_failure(g_parser);
5059 }
5060 END_TEST
5061
5062 /* Test that angle brackets in an attribute default value are faulted */
START_TEST(test_reject_lt_in_attribute_value)5063 START_TEST(test_reject_lt_in_attribute_value) {
5064 const char *text = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '<bar>'>]>\n"
5065 "<doc></doc>";
5066
5067 expect_failure(text, XML_ERROR_INVALID_TOKEN,
5068 "Bad attribute default not faulted");
5069 }
5070 END_TEST
5071
START_TEST(test_reject_unfinished_param_in_att_value)5072 START_TEST(test_reject_unfinished_param_in_att_value) {
5073 const char *text = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '&foo'>]>\n"
5074 "<doc></doc>";
5075
5076 expect_failure(text, XML_ERROR_INVALID_TOKEN,
5077 "Bad attribute default not faulted");
5078 }
5079 END_TEST
5080
START_TEST(test_trailing_cr_in_att_value)5081 START_TEST(test_trailing_cr_in_att_value) {
5082 const char *text = "<doc a='value\r'/>";
5083
5084 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5085 == XML_STATUS_ERROR)
5086 xml_failure(g_parser);
5087 }
5088 END_TEST
5089
5090 /* Try parsing a general entity within a parameter entity in a
5091 * standalone internal DTD. Covers a corner case in the parser.
5092 */
START_TEST(test_standalone_internal_entity)5093 START_TEST(test_standalone_internal_entity) {
5094 const char *text = "<?xml version='1.0' standalone='yes' ?>\n"
5095 "<!DOCTYPE doc [\n"
5096 " <!ELEMENT doc (#PCDATA)>\n"
5097 " <!ENTITY % pe '<!ATTLIST doc att2 CDATA \"≥\">'>\n"
5098 " <!ENTITY ge 'AttDefaultValue'>\n"
5099 " %pe;\n"
5100 "]>\n"
5101 "<doc att2='any'/>";
5102
5103 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5104 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5105 == XML_STATUS_ERROR)
5106 xml_failure(g_parser);
5107 }
5108 END_TEST
5109
5110 /* Test that a reference to an unknown external entity is skipped */
START_TEST(test_skipped_external_entity)5111 START_TEST(test_skipped_external_entity) {
5112 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
5113 "<doc></doc>\n";
5114 ExtTest test_data = {"<!ELEMENT doc EMPTY>\n"
5115 "<!ENTITY % e2 '%e1;'>\n",
5116 NULL, NULL};
5117
5118 XML_SetUserData(g_parser, &test_data);
5119 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5120 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
5121 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5122 == XML_STATUS_ERROR)
5123 xml_failure(g_parser);
5124 }
5125 END_TEST
5126
5127 /* Test a different form of unknown external entity */
5128 typedef struct ext_hdlr_data {
5129 const char *parse_text;
5130 XML_ExternalEntityRefHandler handler;
5131 } ExtHdlrData;
5132
5133 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)5134 external_entity_oneshot_loader(XML_Parser parser, const XML_Char *context,
5135 const XML_Char *base, const XML_Char *systemId,
5136 const XML_Char *publicId) {
5137 ExtHdlrData *test_data = (ExtHdlrData *)XML_GetUserData(parser);
5138 XML_Parser ext_parser;
5139
5140 UNUSED_P(base);
5141 UNUSED_P(systemId);
5142 UNUSED_P(publicId);
5143 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
5144 if (ext_parser == NULL)
5145 fail("Could not create external entity parser.");
5146 /* Use the requested entity parser for further externals */
5147 XML_SetExternalEntityRefHandler(ext_parser, test_data->handler);
5148 if (_XML_Parse_SINGLE_BYTES(ext_parser, test_data->parse_text,
5149 (int)strlen(test_data->parse_text), XML_TRUE)
5150 == XML_STATUS_ERROR) {
5151 xml_failure(ext_parser);
5152 }
5153
5154 XML_ParserFree(ext_parser);
5155 return XML_STATUS_OK;
5156 }
5157
START_TEST(test_skipped_null_loaded_ext_entity)5158 START_TEST(test_skipped_null_loaded_ext_entity) {
5159 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n"
5160 "<doc />";
5161 ExtHdlrData test_data
5162 = {"<!ENTITY % pe1 SYSTEM 'http://example.org/two.ent'>\n"
5163 "<!ENTITY % pe2 '%pe1;'>\n"
5164 "%pe2;\n",
5165 external_entity_null_loader};
5166
5167 XML_SetUserData(g_parser, &test_data);
5168 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5169 XML_SetExternalEntityRefHandler(g_parser, external_entity_oneshot_loader);
5170 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5171 == XML_STATUS_ERROR)
5172 xml_failure(g_parser);
5173 }
5174 END_TEST
5175
START_TEST(test_skipped_unloaded_ext_entity)5176 START_TEST(test_skipped_unloaded_ext_entity) {
5177 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n"
5178 "<doc />";
5179 ExtHdlrData test_data
5180 = {"<!ENTITY % pe1 SYSTEM 'http://example.org/two.ent'>\n"
5181 "<!ENTITY % pe2 '%pe1;'>\n"
5182 "%pe2;\n",
5183 NULL};
5184
5185 XML_SetUserData(g_parser, &test_data);
5186 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5187 XML_SetExternalEntityRefHandler(g_parser, external_entity_oneshot_loader);
5188 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5189 == XML_STATUS_ERROR)
5190 xml_failure(g_parser);
5191 }
5192 END_TEST
5193
5194 /* Test that a parameter entity value ending with a carriage return
5195 * has it translated internally into a newline.
5196 */
START_TEST(test_param_entity_with_trailing_cr)5197 START_TEST(test_param_entity_with_trailing_cr) {
5198 #define PARAM_ENTITY_NAME "pe"
5199 #define PARAM_ENTITY_CORE_VALUE "<!ATTLIST doc att CDATA \"default\">"
5200 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
5201 "<doc/>";
5202 ExtTest test_data
5203 = {"<!ENTITY % " PARAM_ENTITY_NAME " '" PARAM_ENTITY_CORE_VALUE "\r'>\n"
5204 "%" PARAM_ENTITY_NAME ";\n",
5205 NULL, NULL};
5206
5207 XML_SetUserData(g_parser, &test_data);
5208 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5209 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
5210 XML_SetEntityDeclHandler(g_parser, param_entity_match_handler);
5211 entity_name_to_match = XCS(PARAM_ENTITY_NAME);
5212 entity_value_to_match = XCS(PARAM_ENTITY_CORE_VALUE) XCS("\n");
5213 entity_match_flag = ENTITY_MATCH_NOT_FOUND;
5214 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5215 == XML_STATUS_ERROR)
5216 xml_failure(g_parser);
5217 if (entity_match_flag == ENTITY_MATCH_FAIL)
5218 fail("Parameter entity CR->NEWLINE conversion failed");
5219 else if (entity_match_flag == ENTITY_MATCH_NOT_FOUND)
5220 fail("Parameter entity not parsed");
5221 }
5222 #undef PARAM_ENTITY_NAME
5223 #undef PARAM_ENTITY_CORE_VALUE
5224 END_TEST
5225
START_TEST(test_invalid_character_entity)5226 START_TEST(test_invalid_character_entity) {
5227 const char *text = "<!DOCTYPE doc [\n"
5228 " <!ENTITY entity '�'>\n"
5229 "]>\n"
5230 "<doc>&entity;</doc>";
5231
5232 expect_failure(text, XML_ERROR_BAD_CHAR_REF,
5233 "Out of range character reference not faulted");
5234 }
5235 END_TEST
5236
START_TEST(test_invalid_character_entity_2)5237 START_TEST(test_invalid_character_entity_2) {
5238 const char *text = "<!DOCTYPE doc [\n"
5239 " <!ENTITY entity '&#xg0;'>\n"
5240 "]>\n"
5241 "<doc>&entity;</doc>";
5242
5243 expect_failure(text, XML_ERROR_INVALID_TOKEN,
5244 "Out of range character reference not faulted");
5245 }
5246 END_TEST
5247
START_TEST(test_invalid_character_entity_3)5248 START_TEST(test_invalid_character_entity_3) {
5249 const char text[] =
5250 /* <!DOCTYPE doc [\n */
5251 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0\n"
5252 /* U+0E04 = KHO KHWAI
5253 * U+0E08 = CHO CHAN */
5254 /* <!ENTITY entity '&\u0e04\u0e08;'>\n */
5255 "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0e\0n\0t\0i\0t\0y\0 "
5256 "\0'\0&\x0e\x04\x0e\x08\0;\0'\0>\0\n"
5257 /* ]>\n */
5258 "\0]\0>\0\n"
5259 /* <doc>&entity;</doc> */
5260 "\0<\0d\0o\0c\0>\0&\0e\0n\0t\0i\0t\0y\0;\0<\0/\0d\0o\0c\0>";
5261
5262 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5263 != XML_STATUS_ERROR)
5264 fail("Invalid start of entity name not faulted");
5265 if (XML_GetErrorCode(g_parser) != XML_ERROR_UNDEFINED_ENTITY)
5266 xml_failure(g_parser);
5267 }
5268 END_TEST
5269
START_TEST(test_invalid_character_entity_4)5270 START_TEST(test_invalid_character_entity_4) {
5271 const char *text = "<!DOCTYPE doc [\n"
5272 " <!ENTITY entity '�'>\n" /* = � */
5273 "]>\n"
5274 "<doc>&entity;</doc>";
5275
5276 expect_failure(text, XML_ERROR_BAD_CHAR_REF,
5277 "Out of range character reference not faulted");
5278 }
5279 END_TEST
5280
5281 /* Test that processing instructions are picked up by a default handler */
START_TEST(test_pi_handled_in_default)5282 START_TEST(test_pi_handled_in_default) {
5283 const char *text = "<?test processing instruction?>\n<doc/>";
5284 const XML_Char *expected = XCS("<?test processing instruction?>\n<doc/>");
5285 CharData storage;
5286
5287 CharData_Init(&storage);
5288 XML_SetDefaultHandler(g_parser, accumulate_characters);
5289 XML_SetUserData(g_parser, &storage);
5290 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5291 == XML_STATUS_ERROR)
5292 xml_failure(g_parser);
5293 CharData_CheckXMLChars(&storage, expected);
5294 }
5295 END_TEST
5296
5297 /* Test that comments are picked up by a default handler */
START_TEST(test_comment_handled_in_default)5298 START_TEST(test_comment_handled_in_default) {
5299 const char *text = "<!-- This is a comment -->\n<doc/>";
5300 const XML_Char *expected = XCS("<!-- This is a comment -->\n<doc/>");
5301 CharData storage;
5302
5303 CharData_Init(&storage);
5304 XML_SetDefaultHandler(g_parser, accumulate_characters);
5305 XML_SetUserData(g_parser, &storage);
5306 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5307 == XML_STATUS_ERROR)
5308 xml_failure(g_parser);
5309 CharData_CheckXMLChars(&storage, expected);
5310 }
5311 END_TEST
5312
5313 /* Test PIs that look almost but not quite like XML declarations */
5314 static void XMLCALL
accumulate_pi_characters(void * userData,const XML_Char * target,const XML_Char * data)5315 accumulate_pi_characters(void *userData, const XML_Char *target,
5316 const XML_Char *data) {
5317 CharData *storage = (CharData *)userData;
5318
5319 CharData_AppendXMLChars(storage, target, -1);
5320 CharData_AppendXMLChars(storage, XCS(": "), 2);
5321 CharData_AppendXMLChars(storage, data, -1);
5322 CharData_AppendXMLChars(storage, XCS("\n"), 1);
5323 }
5324
START_TEST(test_pi_yml)5325 START_TEST(test_pi_yml) {
5326 const char *text = "<?yml something like data?><doc/>";
5327 const XML_Char *expected = XCS("yml: something like data\n");
5328 CharData storage;
5329
5330 CharData_Init(&storage);
5331 XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5332 XML_SetUserData(g_parser, &storage);
5333 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5334 == XML_STATUS_ERROR)
5335 xml_failure(g_parser);
5336 CharData_CheckXMLChars(&storage, expected);
5337 }
5338 END_TEST
5339
START_TEST(test_pi_xnl)5340 START_TEST(test_pi_xnl) {
5341 const char *text = "<?xnl nothing like data?><doc/>";
5342 const XML_Char *expected = XCS("xnl: nothing like data\n");
5343 CharData storage;
5344
5345 CharData_Init(&storage);
5346 XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5347 XML_SetUserData(g_parser, &storage);
5348 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5349 == XML_STATUS_ERROR)
5350 xml_failure(g_parser);
5351 CharData_CheckXMLChars(&storage, expected);
5352 }
5353 END_TEST
5354
START_TEST(test_pi_xmm)5355 START_TEST(test_pi_xmm) {
5356 const char *text = "<?xmm everything like data?><doc/>";
5357 const XML_Char *expected = XCS("xmm: everything like data\n");
5358 CharData storage;
5359
5360 CharData_Init(&storage);
5361 XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5362 XML_SetUserData(g_parser, &storage);
5363 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5364 == XML_STATUS_ERROR)
5365 xml_failure(g_parser);
5366 CharData_CheckXMLChars(&storage, expected);
5367 }
5368 END_TEST
5369
START_TEST(test_utf16_pi)5370 START_TEST(test_utf16_pi) {
5371 const char text[] =
5372 /* <?{KHO KHWAI}{CHO CHAN}?>
5373 * where {KHO KHWAI} = U+0E04
5374 * and {CHO CHAN} = U+0E08
5375 */
5376 "<\0?\0\x04\x0e\x08\x0e?\0>\0"
5377 /* <q/> */
5378 "<\0q\0/\0>\0";
5379 #ifdef XML_UNICODE
5380 const XML_Char *expected = XCS("\x0e04\x0e08: \n");
5381 #else
5382 const XML_Char *expected = XCS("\xe0\xb8\x84\xe0\xb8\x88: \n");
5383 #endif
5384 CharData storage;
5385
5386 CharData_Init(&storage);
5387 XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5388 XML_SetUserData(g_parser, &storage);
5389 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5390 == XML_STATUS_ERROR)
5391 xml_failure(g_parser);
5392 CharData_CheckXMLChars(&storage, expected);
5393 }
5394 END_TEST
5395
START_TEST(test_utf16_be_pi)5396 START_TEST(test_utf16_be_pi) {
5397 const char text[] =
5398 /* <?{KHO KHWAI}{CHO CHAN}?>
5399 * where {KHO KHWAI} = U+0E04
5400 * and {CHO CHAN} = U+0E08
5401 */
5402 "\0<\0?\x0e\x04\x0e\x08\0?\0>"
5403 /* <q/> */
5404 "\0<\0q\0/\0>";
5405 #ifdef XML_UNICODE
5406 const XML_Char *expected = XCS("\x0e04\x0e08: \n");
5407 #else
5408 const XML_Char *expected = XCS("\xe0\xb8\x84\xe0\xb8\x88: \n");
5409 #endif
5410 CharData storage;
5411
5412 CharData_Init(&storage);
5413 XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5414 XML_SetUserData(g_parser, &storage);
5415 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5416 == XML_STATUS_ERROR)
5417 xml_failure(g_parser);
5418 CharData_CheckXMLChars(&storage, expected);
5419 }
5420 END_TEST
5421
5422 /* Test that comments can be picked up and translated */
5423 static void XMLCALL
accumulate_comment(void * userData,const XML_Char * data)5424 accumulate_comment(void *userData, const XML_Char *data) {
5425 CharData *storage = (CharData *)userData;
5426
5427 CharData_AppendXMLChars(storage, data, -1);
5428 }
5429
START_TEST(test_utf16_be_comment)5430 START_TEST(test_utf16_be_comment) {
5431 const char text[] =
5432 /* <!-- Comment A --> */
5433 "\0<\0!\0-\0-\0 \0C\0o\0m\0m\0e\0n\0t\0 \0A\0 \0-\0-\0>\0\n"
5434 /* <doc/> */
5435 "\0<\0d\0o\0c\0/\0>";
5436 const XML_Char *expected = XCS(" Comment A ");
5437 CharData storage;
5438
5439 CharData_Init(&storage);
5440 XML_SetCommentHandler(g_parser, accumulate_comment);
5441 XML_SetUserData(g_parser, &storage);
5442 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5443 == XML_STATUS_ERROR)
5444 xml_failure(g_parser);
5445 CharData_CheckXMLChars(&storage, expected);
5446 }
5447 END_TEST
5448
START_TEST(test_utf16_le_comment)5449 START_TEST(test_utf16_le_comment) {
5450 const char text[] =
5451 /* <!-- Comment B --> */
5452 "<\0!\0-\0-\0 \0C\0o\0m\0m\0e\0n\0t\0 \0B\0 \0-\0-\0>\0\n\0"
5453 /* <doc/> */
5454 "<\0d\0o\0c\0/\0>\0";
5455 const XML_Char *expected = XCS(" Comment B ");
5456 CharData storage;
5457
5458 CharData_Init(&storage);
5459 XML_SetCommentHandler(g_parser, accumulate_comment);
5460 XML_SetUserData(g_parser, &storage);
5461 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5462 == XML_STATUS_ERROR)
5463 xml_failure(g_parser);
5464 CharData_CheckXMLChars(&storage, expected);
5465 }
5466 END_TEST
5467
5468 /* Test that the unknown encoding handler with map entries that expect
5469 * conversion but no conversion function is faulted
5470 */
5471 static int XMLCALL
failing_converter(void * data,const char * s)5472 failing_converter(void *data, const char *s) {
5473 UNUSED_P(data);
5474 UNUSED_P(s);
5475 /* Always claim to have failed */
5476 return -1;
5477 }
5478
5479 static int XMLCALL
prefix_converter(void * data,const char * s)5480 prefix_converter(void *data, const char *s) {
5481 UNUSED_P(data);
5482 /* If the first byte is 0xff, raise an error */
5483 if (s[0] == (char)-1)
5484 return -1;
5485 /* Just add the low bits of the first byte to the second */
5486 return (s[1] + (s[0] & 0x7f)) & 0x01ff;
5487 }
5488
5489 static int XMLCALL
MiscEncodingHandler(void * data,const XML_Char * encoding,XML_Encoding * info)5490 MiscEncodingHandler(void *data, const XML_Char *encoding, XML_Encoding *info) {
5491 int i;
5492 int high_map = -2; /* Assume a 2-byte sequence */
5493
5494 if (! xcstrcmp(encoding, XCS("invalid-9"))
5495 || ! xcstrcmp(encoding, XCS("ascii-like"))
5496 || ! xcstrcmp(encoding, XCS("invalid-len"))
5497 || ! xcstrcmp(encoding, XCS("invalid-a"))
5498 || ! xcstrcmp(encoding, XCS("invalid-surrogate"))
5499 || ! xcstrcmp(encoding, XCS("invalid-high")))
5500 high_map = -1;
5501
5502 for (i = 0; i < 128; ++i)
5503 info->map[i] = i;
5504 for (; i < 256; ++i)
5505 info->map[i] = high_map;
5506
5507 /* If required, put an invalid value in the ASCII entries */
5508 if (! xcstrcmp(encoding, XCS("invalid-9")))
5509 info->map[9] = 5;
5510 /* If required, have a top-bit set character starts a 5-byte sequence */
5511 if (! xcstrcmp(encoding, XCS("invalid-len")))
5512 info->map[0x81] = -5;
5513 /* If required, make a top-bit set character a valid ASCII character */
5514 if (! xcstrcmp(encoding, XCS("invalid-a")))
5515 info->map[0x82] = 'a';
5516 /* If required, give a top-bit set character a forbidden value,
5517 * what would otherwise be the first of a surrogate pair.
5518 */
5519 if (! xcstrcmp(encoding, XCS("invalid-surrogate")))
5520 info->map[0x83] = 0xd801;
5521 /* If required, give a top-bit set character too high a value */
5522 if (! xcstrcmp(encoding, XCS("invalid-high")))
5523 info->map[0x84] = 0x010101;
5524
5525 info->data = data;
5526 info->release = NULL;
5527 if (! xcstrcmp(encoding, XCS("failing-conv")))
5528 info->convert = failing_converter;
5529 else if (! xcstrcmp(encoding, XCS("prefix-conv")))
5530 info->convert = prefix_converter;
5531 else
5532 info->convert = NULL;
5533 return XML_STATUS_OK;
5534 }
5535
START_TEST(test_missing_encoding_conversion_fn)5536 START_TEST(test_missing_encoding_conversion_fn) {
5537 const char *text = "<?xml version='1.0' encoding='no-conv'?>\n"
5538 "<doc>\x81</doc>";
5539
5540 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5541 /* MiscEncodingHandler sets up an encoding with every top-bit-set
5542 * character introducing a two-byte sequence. For this, it
5543 * requires a convert function. The above function call doesn't
5544 * pass one through, so when BadEncodingHandler actually gets
5545 * called it should supply an invalid encoding.
5546 */
5547 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5548 "Encoding with missing convert() not faulted");
5549 }
5550 END_TEST
5551
START_TEST(test_failing_encoding_conversion_fn)5552 START_TEST(test_failing_encoding_conversion_fn) {
5553 const char *text = "<?xml version='1.0' encoding='failing-conv'?>\n"
5554 "<doc>\x81</doc>";
5555
5556 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5557 /* BadEncodingHandler sets up an encoding with every top-bit-set
5558 * character introducing a two-byte sequence. For this, it
5559 * requires a convert function. The above function call passes
5560 * one that insists all possible sequences are invalid anyway.
5561 */
5562 expect_failure(text, XML_ERROR_INVALID_TOKEN,
5563 "Encoding with failing convert() not faulted");
5564 }
5565 END_TEST
5566
5567 /* Test unknown encoding conversions */
START_TEST(test_unknown_encoding_success)5568 START_TEST(test_unknown_encoding_success) {
5569 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5570 /* Equivalent to <eoc>Hello, world</eoc> */
5571 "<\x81\x64\x80oc>Hello, world</\x81\x64\x80oc>";
5572
5573 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5574 run_character_check(text, XCS("Hello, world"));
5575 }
5576 END_TEST
5577
5578 /* Test bad name character in unknown encoding */
START_TEST(test_unknown_encoding_bad_name)5579 START_TEST(test_unknown_encoding_bad_name) {
5580 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5581 "<\xff\x64oc>Hello, world</\xff\x64oc>";
5582
5583 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5584 expect_failure(text, XML_ERROR_INVALID_TOKEN,
5585 "Bad name start in unknown encoding not faulted");
5586 }
5587 END_TEST
5588
5589 /* Test bad mid-name character in unknown encoding */
START_TEST(test_unknown_encoding_bad_name_2)5590 START_TEST(test_unknown_encoding_bad_name_2) {
5591 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5592 "<d\xffoc>Hello, world</d\xffoc>";
5593
5594 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5595 expect_failure(text, XML_ERROR_INVALID_TOKEN,
5596 "Bad name in unknown encoding not faulted");
5597 }
5598 END_TEST
5599
5600 /* Test element name that is long enough to fill the conversion buffer
5601 * in an unknown encoding, finishing with an encoded character.
5602 */
START_TEST(test_unknown_encoding_long_name_1)5603 START_TEST(test_unknown_encoding_long_name_1) {
5604 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5605 "<abcdefghabcdefghabcdefghijkl\x80m\x80n\x80o\x80p>"
5606 "Hi"
5607 "</abcdefghabcdefghabcdefghijkl\x80m\x80n\x80o\x80p>";
5608 const XML_Char *expected = XCS("abcdefghabcdefghabcdefghijklmnop");
5609 CharData storage;
5610
5611 CharData_Init(&storage);
5612 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5613 XML_SetStartElementHandler(g_parser, record_element_start_handler);
5614 XML_SetUserData(g_parser, &storage);
5615 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5616 == XML_STATUS_ERROR)
5617 xml_failure(g_parser);
5618 CharData_CheckXMLChars(&storage, expected);
5619 }
5620 END_TEST
5621
5622 /* Test element name that is long enough to fill the conversion buffer
5623 * in an unknown encoding, finishing with an simple character.
5624 */
START_TEST(test_unknown_encoding_long_name_2)5625 START_TEST(test_unknown_encoding_long_name_2) {
5626 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5627 "<abcdefghabcdefghabcdefghijklmnop>"
5628 "Hi"
5629 "</abcdefghabcdefghabcdefghijklmnop>";
5630 const XML_Char *expected = XCS("abcdefghabcdefghabcdefghijklmnop");
5631 CharData storage;
5632
5633 CharData_Init(&storage);
5634 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5635 XML_SetStartElementHandler(g_parser, record_element_start_handler);
5636 XML_SetUserData(g_parser, &storage);
5637 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5638 == XML_STATUS_ERROR)
5639 xml_failure(g_parser);
5640 CharData_CheckXMLChars(&storage, expected);
5641 }
5642 END_TEST
5643
START_TEST(test_invalid_unknown_encoding)5644 START_TEST(test_invalid_unknown_encoding) {
5645 const char *text = "<?xml version='1.0' encoding='invalid-9'?>\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_ascii_encoding_ok)5654 START_TEST(test_unknown_ascii_encoding_ok) {
5655 const char *text = "<?xml version='1.0' encoding='ascii-like'?>\n"
5656 "<doc>Hello, world</doc>";
5657
5658 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5659 run_character_check(text, XCS("Hello, world"));
5660 }
5661 END_TEST
5662
START_TEST(test_unknown_ascii_encoding_fail)5663 START_TEST(test_unknown_ascii_encoding_fail) {
5664 const char *text = "<?xml version='1.0' encoding='ascii-like'?>\n"
5665 "<doc>Hello, \x80 world</doc>";
5666
5667 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5668 expect_failure(text, XML_ERROR_INVALID_TOKEN,
5669 "Invalid character not faulted");
5670 }
5671 END_TEST
5672
START_TEST(test_unknown_encoding_invalid_length)5673 START_TEST(test_unknown_encoding_invalid_length) {
5674 const char *text = "<?xml version='1.0' encoding='invalid-len'?>\n"
5675 "<doc>Hello, world</doc>";
5676
5677 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5678 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5679 "Invalid unknown encoding not faulted");
5680 }
5681 END_TEST
5682
START_TEST(test_unknown_encoding_invalid_topbit)5683 START_TEST(test_unknown_encoding_invalid_topbit) {
5684 const char *text = "<?xml version='1.0' encoding='invalid-a'?>\n"
5685 "<doc>Hello, world</doc>";
5686
5687 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5688 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5689 "Invalid unknown encoding not faulted");
5690 }
5691 END_TEST
5692
START_TEST(test_unknown_encoding_invalid_surrogate)5693 START_TEST(test_unknown_encoding_invalid_surrogate) {
5694 const char *text = "<?xml version='1.0' encoding='invalid-surrogate'?>\n"
5695 "<doc>Hello, \x82 world</doc>";
5696
5697 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5698 expect_failure(text, XML_ERROR_INVALID_TOKEN,
5699 "Invalid unknown encoding not faulted");
5700 }
5701 END_TEST
5702
START_TEST(test_unknown_encoding_invalid_high)5703 START_TEST(test_unknown_encoding_invalid_high) {
5704 const char *text = "<?xml version='1.0' encoding='invalid-high'?>\n"
5705 "<doc>Hello, world</doc>";
5706
5707 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5708 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5709 "Invalid unknown encoding not faulted");
5710 }
5711 END_TEST
5712
START_TEST(test_unknown_encoding_invalid_attr_value)5713 START_TEST(test_unknown_encoding_invalid_attr_value) {
5714 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5715 "<doc attr='\xff\x30'/>";
5716
5717 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5718 expect_failure(text, XML_ERROR_INVALID_TOKEN,
5719 "Invalid attribute valid not faulted");
5720 }
5721 END_TEST
5722
5723 /* Test an external entity parser set to use latin-1 detects UTF-16
5724 * BOMs correctly.
5725 */
5726 enum ee_parse_flags { EE_PARSE_NONE = 0x00, EE_PARSE_FULL_BUFFER = 0x01 };
5727
5728 typedef struct ExtTest2 {
5729 const char *parse_text;
5730 int parse_len;
5731 const XML_Char *encoding;
5732 CharData *storage;
5733 enum ee_parse_flags flags;
5734 } ExtTest2;
5735
5736 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)5737 external_entity_loader2(XML_Parser parser, const XML_Char *context,
5738 const XML_Char *base, const XML_Char *systemId,
5739 const XML_Char *publicId) {
5740 ExtTest2 *test_data = (ExtTest2 *)XML_GetUserData(parser);
5741 XML_Parser extparser;
5742
5743 UNUSED_P(base);
5744 UNUSED_P(systemId);
5745 UNUSED_P(publicId);
5746 extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
5747 if (extparser == NULL)
5748 fail("Coulr not create external entity parser");
5749 if (test_data->encoding != NULL) {
5750 if (! XML_SetEncoding(extparser, test_data->encoding))
5751 fail("XML_SetEncoding() ignored for external entity");
5752 }
5753 if (test_data->flags & EE_PARSE_FULL_BUFFER) {
5754 if (XML_Parse(extparser, test_data->parse_text, test_data->parse_len,
5755 XML_TRUE)
5756 == XML_STATUS_ERROR) {
5757 xml_failure(extparser);
5758 }
5759 } else if (_XML_Parse_SINGLE_BYTES(extparser, test_data->parse_text,
5760 test_data->parse_len, XML_TRUE)
5761 == XML_STATUS_ERROR) {
5762 xml_failure(extparser);
5763 }
5764
5765 XML_ParserFree(extparser);
5766 return XML_STATUS_OK;
5767 }
5768
5769 /* Test that UTF-16 BOM does not select UTF-16 given explicit encoding */
5770 static void XMLCALL
ext2_accumulate_characters(void * userData,const XML_Char * s,int len)5771 ext2_accumulate_characters(void *userData, const XML_Char *s, int len) {
5772 ExtTest2 *test_data = (ExtTest2 *)userData;
5773 accumulate_characters(test_data->storage, s, len);
5774 }
5775
START_TEST(test_ext_entity_latin1_utf16le_bom)5776 START_TEST(test_ext_entity_latin1_utf16le_bom) {
5777 const char *text = "<!DOCTYPE doc [\n"
5778 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5779 "]>\n"
5780 "<doc>&en;</doc>";
5781 ExtTest2 test_data
5782 = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */
5783 /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn,
5784 * 0x4c = L and 0x20 is a space
5785 */
5786 "\xff\xfe\x4c\x20", 4, XCS("iso-8859-1"), NULL, EE_PARSE_NONE};
5787 #ifdef XML_UNICODE
5788 const XML_Char *expected = XCS("\x00ff\x00feL ");
5789 #else
5790 /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */
5791 const XML_Char *expected = XCS("\xc3\xbf\xc3\xbeL ");
5792 #endif
5793 CharData storage;
5794
5795 CharData_Init(&storage);
5796 test_data.storage = &storage;
5797 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5798 XML_SetUserData(g_parser, &test_data);
5799 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5800 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5801 == XML_STATUS_ERROR)
5802 xml_failure(g_parser);
5803 CharData_CheckXMLChars(&storage, expected);
5804 }
5805 END_TEST
5806
START_TEST(test_ext_entity_latin1_utf16be_bom)5807 START_TEST(test_ext_entity_latin1_utf16be_bom) {
5808 const char *text = "<!DOCTYPE doc [\n"
5809 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5810 "]>\n"
5811 "<doc>&en;</doc>";
5812 ExtTest2 test_data
5813 = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */
5814 /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn,
5815 * 0x4c = L and 0x20 is a space
5816 */
5817 "\xfe\xff\x20\x4c", 4, XCS("iso-8859-1"), NULL, EE_PARSE_NONE};
5818 #ifdef XML_UNICODE
5819 const XML_Char *expected = XCS("\x00fe\x00ff L");
5820 #else
5821 /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */
5822 const XML_Char *expected = XCS("\xc3\xbe\xc3\xbf L");
5823 #endif
5824 CharData storage;
5825
5826 CharData_Init(&storage);
5827 test_data.storage = &storage;
5828 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5829 XML_SetUserData(g_parser, &test_data);
5830 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5831 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5832 == XML_STATUS_ERROR)
5833 xml_failure(g_parser);
5834 CharData_CheckXMLChars(&storage, expected);
5835 }
5836 END_TEST
5837
5838 /* Parsing the full buffer rather than a byte at a time makes a
5839 * difference to the encoding scanning code, so repeat the above tests
5840 * without breaking them down by byte.
5841 */
START_TEST(test_ext_entity_latin1_utf16le_bom2)5842 START_TEST(test_ext_entity_latin1_utf16le_bom2) {
5843 const char *text = "<!DOCTYPE doc [\n"
5844 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5845 "]>\n"
5846 "<doc>&en;</doc>";
5847 ExtTest2 test_data
5848 = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */
5849 /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn,
5850 * 0x4c = L and 0x20 is a space
5851 */
5852 "\xff\xfe\x4c\x20", 4, XCS("iso-8859-1"), NULL, EE_PARSE_FULL_BUFFER};
5853 #ifdef XML_UNICODE
5854 const XML_Char *expected = XCS("\x00ff\x00feL ");
5855 #else
5856 /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */
5857 const XML_Char *expected = XCS("\xc3\xbf\xc3\xbeL ");
5858 #endif
5859 CharData storage;
5860
5861 CharData_Init(&storage);
5862 test_data.storage = &storage;
5863 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5864 XML_SetUserData(g_parser, &test_data);
5865 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5866 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
5867 == XML_STATUS_ERROR)
5868 xml_failure(g_parser);
5869 CharData_CheckXMLChars(&storage, expected);
5870 }
5871 END_TEST
5872
START_TEST(test_ext_entity_latin1_utf16be_bom2)5873 START_TEST(test_ext_entity_latin1_utf16be_bom2) {
5874 const char *text = "<!DOCTYPE doc [\n"
5875 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5876 "]>\n"
5877 "<doc>&en;</doc>";
5878 ExtTest2 test_data
5879 = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */
5880 /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn,
5881 * 0x4c = L and 0x20 is a space
5882 */
5883 "\xfe\xff\x20\x4c", 4, XCS("iso-8859-1"), NULL, EE_PARSE_FULL_BUFFER};
5884 #ifdef XML_UNICODE
5885 const XML_Char *expected = XCS("\x00fe\x00ff L");
5886 #else
5887 /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */
5888 const XML_Char *expected = "\xc3\xbe\xc3\xbf L";
5889 #endif
5890 CharData storage;
5891
5892 CharData_Init(&storage);
5893 test_data.storage = &storage;
5894 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5895 XML_SetUserData(g_parser, &test_data);
5896 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5897 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
5898 == XML_STATUS_ERROR)
5899 xml_failure(g_parser);
5900 CharData_CheckXMLChars(&storage, expected);
5901 }
5902 END_TEST
5903
5904 /* Test little-endian UTF-16 given an explicit big-endian encoding */
START_TEST(test_ext_entity_utf16_be)5905 START_TEST(test_ext_entity_utf16_be) {
5906 const char *text = "<!DOCTYPE doc [\n"
5907 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5908 "]>\n"
5909 "<doc>&en;</doc>";
5910 ExtTest2 test_data
5911 = {"<\0e\0/\0>\0", 8, XCS("utf-16be"), NULL, EE_PARSE_NONE};
5912 #ifdef XML_UNICODE
5913 const XML_Char *expected = XCS("\x3c00\x6500\x2f00\x3e00");
5914 #else
5915 const XML_Char *expected = XCS("\xe3\xb0\x80" /* U+3C00 */
5916 "\xe6\x94\x80" /* U+6500 */
5917 "\xe2\xbc\x80" /* U+2F00 */
5918 "\xe3\xb8\x80"); /* U+3E00 */
5919 #endif
5920 CharData storage;
5921
5922 CharData_Init(&storage);
5923 test_data.storage = &storage;
5924 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5925 XML_SetUserData(g_parser, &test_data);
5926 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5927 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5928 == XML_STATUS_ERROR)
5929 xml_failure(g_parser);
5930 CharData_CheckXMLChars(&storage, expected);
5931 }
5932 END_TEST
5933
5934 /* Test big-endian UTF-16 given an explicit little-endian encoding */
START_TEST(test_ext_entity_utf16_le)5935 START_TEST(test_ext_entity_utf16_le) {
5936 const char *text = "<!DOCTYPE doc [\n"
5937 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5938 "]>\n"
5939 "<doc>&en;</doc>";
5940 ExtTest2 test_data
5941 = {"\0<\0e\0/\0>", 8, XCS("utf-16le"), NULL, EE_PARSE_NONE};
5942 #ifdef XML_UNICODE
5943 const XML_Char *expected = XCS("\x3c00\x6500\x2f00\x3e00");
5944 #else
5945 const XML_Char *expected = XCS("\xe3\xb0\x80" /* U+3C00 */
5946 "\xe6\x94\x80" /* U+6500 */
5947 "\xe2\xbc\x80" /* U+2F00 */
5948 "\xe3\xb8\x80"); /* U+3E00 */
5949 #endif
5950 CharData storage;
5951
5952 CharData_Init(&storage);
5953 test_data.storage = &storage;
5954 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5955 XML_SetUserData(g_parser, &test_data);
5956 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5957 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5958 == XML_STATUS_ERROR)
5959 xml_failure(g_parser);
5960 CharData_CheckXMLChars(&storage, expected);
5961 }
5962 END_TEST
5963
5964 /* Test little-endian UTF-16 given no explicit encoding.
5965 * The existing default encoding (UTF-8) is assumed to hold without a
5966 * BOM to contradict it, so the entity value will in fact provoke an
5967 * error because 0x00 is not a valid XML character. We parse the
5968 * whole buffer in one go rather than feeding it in byte by byte to
5969 * exercise different code paths in the initial scanning routines.
5970 */
5971 typedef struct ExtFaults2 {
5972 const char *parse_text;
5973 int parse_len;
5974 const char *fail_text;
5975 const XML_Char *encoding;
5976 enum XML_Error error;
5977 } ExtFaults2;
5978
5979 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)5980 external_entity_faulter2(XML_Parser parser, const XML_Char *context,
5981 const XML_Char *base, const XML_Char *systemId,
5982 const XML_Char *publicId) {
5983 ExtFaults2 *test_data = (ExtFaults2 *)XML_GetUserData(parser);
5984 XML_Parser extparser;
5985
5986 UNUSED_P(base);
5987 UNUSED_P(systemId);
5988 UNUSED_P(publicId);
5989 extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
5990 if (extparser == NULL)
5991 fail("Could not create external entity parser");
5992 if (test_data->encoding != NULL) {
5993 if (! XML_SetEncoding(extparser, test_data->encoding))
5994 fail("XML_SetEncoding() ignored for external entity");
5995 }
5996 if (XML_Parse(extparser, test_data->parse_text, test_data->parse_len,
5997 XML_TRUE)
5998 != XML_STATUS_ERROR)
5999 fail(test_data->fail_text);
6000 if (XML_GetErrorCode(extparser) != test_data->error)
6001 xml_failure(extparser);
6002
6003 XML_ParserFree(extparser);
6004 return XML_STATUS_ERROR;
6005 }
6006
START_TEST(test_ext_entity_utf16_unknown)6007 START_TEST(test_ext_entity_utf16_unknown) {
6008 const char *text = "<!DOCTYPE doc [\n"
6009 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
6010 "]>\n"
6011 "<doc>&en;</doc>";
6012 ExtFaults2 test_data
6013 = {"a\0b\0c\0", 6, "Invalid character in entity not faulted", NULL,
6014 XML_ERROR_INVALID_TOKEN};
6015
6016 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter2);
6017 XML_SetUserData(g_parser, &test_data);
6018 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
6019 "Invalid character should not have been accepted");
6020 }
6021 END_TEST
6022
6023 /* Test not-quite-UTF-8 BOM (0xEF 0xBB 0xBF) */
START_TEST(test_ext_entity_utf8_non_bom)6024 START_TEST(test_ext_entity_utf8_non_bom) {
6025 const char *text = "<!DOCTYPE doc [\n"
6026 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
6027 "]>\n"
6028 "<doc>&en;</doc>";
6029 ExtTest2 test_data
6030 = {"\xef\xbb\x80", /* Arabic letter DAD medial form, U+FEC0 */
6031 3, NULL, NULL, EE_PARSE_NONE};
6032 #ifdef XML_UNICODE
6033 const XML_Char *expected = XCS("\xfec0");
6034 #else
6035 const XML_Char *expected = XCS("\xef\xbb\x80");
6036 #endif
6037 CharData storage;
6038
6039 CharData_Init(&storage);
6040 test_data.storage = &storage;
6041 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
6042 XML_SetUserData(g_parser, &test_data);
6043 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
6044 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6045 == XML_STATUS_ERROR)
6046 xml_failure(g_parser);
6047 CharData_CheckXMLChars(&storage, expected);
6048 }
6049 END_TEST
6050
6051 /* Test that UTF-8 in a CDATA section is correctly passed through */
START_TEST(test_utf8_in_cdata_section)6052 START_TEST(test_utf8_in_cdata_section) {
6053 const char *text = "<doc><![CDATA[one \xc3\xa9 two]]></doc>";
6054 #ifdef XML_UNICODE
6055 const XML_Char *expected = XCS("one \x00e9 two");
6056 #else
6057 const XML_Char *expected = XCS("one \xc3\xa9 two");
6058 #endif
6059
6060 run_character_check(text, expected);
6061 }
6062 END_TEST
6063
6064 /* Test that little-endian UTF-16 in a CDATA section is handled */
START_TEST(test_utf8_in_cdata_section_2)6065 START_TEST(test_utf8_in_cdata_section_2) {
6066 const char *text = "<doc><![CDATA[\xc3\xa9]\xc3\xa9two]]></doc>";
6067 #ifdef XML_UNICODE
6068 const XML_Char *expected = XCS("\x00e9]\x00e9two");
6069 #else
6070 const XML_Char *expected = XCS("\xc3\xa9]\xc3\xa9two");
6071 #endif
6072
6073 run_character_check(text, expected);
6074 }
6075 END_TEST
6076
START_TEST(test_utf8_in_start_tags)6077 START_TEST(test_utf8_in_start_tags) {
6078 struct test_case {
6079 bool goodName;
6080 bool goodNameStart;
6081 const char *tagName;
6082 };
6083
6084 // The idea with the tests below is this:
6085 // We want to cover 1-, 2- and 3-byte sequences, 4-byte sequences
6086 // go to isNever and are hence not a concern.
6087 //
6088 // We start with a character that is a valid name character
6089 // (or even name-start character, see XML 1.0r4 spec) and then we flip
6090 // single bits at places where (1) the result leaves the UTF-8 encoding space
6091 // and (2) we stay in the same n-byte sequence family.
6092 //
6093 // The flipped bits are highlighted in angle brackets in comments,
6094 // e.g. "[<1>011 1001]" means we had [0011 1001] but we now flipped
6095 // the most significant bit to 1 to leave UTF-8 encoding space.
6096 struct test_case cases[] = {
6097 // 1-byte UTF-8: [0xxx xxxx]
6098 {true, true, "\x3A"}, // [0011 1010] = ASCII colon ':'
6099 {false, false, "\xBA"}, // [<1>011 1010]
6100 {true, false, "\x39"}, // [0011 1001] = ASCII nine '9'
6101 {false, false, "\xB9"}, // [<1>011 1001]
6102
6103 // 2-byte UTF-8: [110x xxxx] [10xx xxxx]
6104 {true, true, "\xDB\xA5"}, // [1101 1011] [1010 0101] =
6105 // Arabic small waw U+06E5
6106 {false, false, "\x9B\xA5"}, // [1<0>01 1011] [1010 0101]
6107 {false, false, "\xDB\x25"}, // [1101 1011] [<0>010 0101]
6108 {false, false, "\xDB\xE5"}, // [1101 1011] [1<1>10 0101]
6109 {true, false, "\xCC\x81"}, // [1100 1100] [1000 0001] =
6110 // combining char U+0301
6111 {false, false, "\x8C\x81"}, // [1<0>00 1100] [1000 0001]
6112 {false, false, "\xCC\x01"}, // [1100 1100] [<0>000 0001]
6113 {false, false, "\xCC\xC1"}, // [1100 1100] [1<1>00 0001]
6114
6115 // 3-byte UTF-8: [1110 xxxx] [10xx xxxx] [10xxxxxx]
6116 {true, true, "\xE0\xA4\x85"}, // [1110 0000] [1010 0100] [1000 0101] =
6117 // Devanagari Letter A U+0905
6118 {false, false, "\xA0\xA4\x85"}, // [1<0>10 0000] [1010 0100] [1000 0101]
6119 {false, false, "\xE0\x24\x85"}, // [1110 0000] [<0>010 0100] [1000 0101]
6120 {false, false, "\xE0\xE4\x85"}, // [1110 0000] [1<1>10 0100] [1000 0101]
6121 {false, false, "\xE0\xA4\x05"}, // [1110 0000] [1010 0100] [<0>000 0101]
6122 {false, false, "\xE0\xA4\xC5"}, // [1110 0000] [1010 0100] [1<1>00 0101]
6123 {true, false, "\xE0\xA4\x81"}, // [1110 0000] [1010 0100] [1000 0001] =
6124 // combining char U+0901
6125 {false, false, "\xA0\xA4\x81"}, // [1<0>10 0000] [1010 0100] [1000 0001]
6126 {false, false, "\xE0\x24\x81"}, // [1110 0000] [<0>010 0100] [1000 0001]
6127 {false, false, "\xE0\xE4\x81"}, // [1110 0000] [1<1>10 0100] [1000 0001]
6128 {false, false, "\xE0\xA4\x01"}, // [1110 0000] [1010 0100] [<0>000 0001]
6129 {false, false, "\xE0\xA4\xC1"}, // [1110 0000] [1010 0100] [1<1>00 0001]
6130 };
6131 const bool atNameStart[] = {true, false};
6132
6133 size_t i = 0;
6134 char doc[1024];
6135 size_t failCount = 0;
6136
6137 for (; i < sizeof(cases) / sizeof(cases[0]); i++) {
6138 size_t j = 0;
6139 for (; j < sizeof(atNameStart) / sizeof(atNameStart[0]); j++) {
6140 const bool expectedSuccess
6141 = atNameStart[j] ? cases[i].goodNameStart : cases[i].goodName;
6142 sprintf(doc, "<%s%s><!--", atNameStart[j] ? "" : "a", cases[i].tagName);
6143 XML_Parser parser = XML_ParserCreate(NULL);
6144
6145 const enum XML_Status status
6146 = XML_Parse(parser, doc, (int)strlen(doc), /*isFinal=*/XML_FALSE);
6147
6148 bool success = true;
6149 if ((status == XML_STATUS_OK) != expectedSuccess) {
6150 success = false;
6151 }
6152 if ((status == XML_STATUS_ERROR)
6153 && (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN)) {
6154 success = false;
6155 }
6156
6157 if (! success) {
6158 fprintf(
6159 stderr,
6160 "FAIL case %2u (%sat name start, %u-byte sequence, error code %d)\n",
6161 (unsigned)i + 1u, atNameStart[j] ? " " : "not ",
6162 (unsigned)strlen(cases[i].tagName), XML_GetErrorCode(parser));
6163 failCount++;
6164 }
6165
6166 XML_ParserFree(parser);
6167 }
6168 }
6169
6170 if (failCount > 0) {
6171 fail("UTF-8 regression detected");
6172 }
6173 }
6174 END_TEST
6175
6176 /* Test trailing spaces in elements are accepted */
6177 static void XMLCALL
record_element_end_handler(void * userData,const XML_Char * name)6178 record_element_end_handler(void *userData, const XML_Char *name) {
6179 CharData *storage = (CharData *)userData;
6180
6181 CharData_AppendXMLChars(storage, XCS("/"), 1);
6182 CharData_AppendXMLChars(storage, name, -1);
6183 }
6184
START_TEST(test_trailing_spaces_in_elements)6185 START_TEST(test_trailing_spaces_in_elements) {
6186 const char *text = "<doc >Hi</doc >";
6187 const XML_Char *expected = XCS("doc/doc");
6188 CharData storage;
6189
6190 CharData_Init(&storage);
6191 XML_SetElementHandler(g_parser, record_element_start_handler,
6192 record_element_end_handler);
6193 XML_SetUserData(g_parser, &storage);
6194 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6195 == XML_STATUS_ERROR)
6196 xml_failure(g_parser);
6197 CharData_CheckXMLChars(&storage, expected);
6198 }
6199 END_TEST
6200
START_TEST(test_utf16_attribute)6201 START_TEST(test_utf16_attribute) {
6202 const char text[] =
6203 /* <d {KHO KHWAI}{CHO CHAN}='a'/>
6204 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
6205 * and {CHO CHAN} = U+0E08 = 0xe0 0xb8 0x88 in UTF-8
6206 */
6207 "<\0d\0 \0\x04\x0e\x08\x0e=\0'\0a\0'\0/\0>\0";
6208 const XML_Char *expected = XCS("a");
6209 CharData storage;
6210
6211 CharData_Init(&storage);
6212 XML_SetStartElementHandler(g_parser, accumulate_attribute);
6213 XML_SetUserData(g_parser, &storage);
6214 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6215 == XML_STATUS_ERROR)
6216 xml_failure(g_parser);
6217 CharData_CheckXMLChars(&storage, expected);
6218 }
6219 END_TEST
6220
START_TEST(test_utf16_second_attr)6221 START_TEST(test_utf16_second_attr) {
6222 /* <d a='1' {KHO KHWAI}{CHO CHAN}='2'/>
6223 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
6224 * and {CHO CHAN} = U+0E08 = 0xe0 0xb8 0x88 in UTF-8
6225 */
6226 const char text[] = "<\0d\0 \0a\0=\0'\0\x31\0'\0 \0"
6227 "\x04\x0e\x08\x0e=\0'\0\x32\0'\0/\0>\0";
6228 const XML_Char *expected = XCS("1");
6229 CharData storage;
6230
6231 CharData_Init(&storage);
6232 XML_SetStartElementHandler(g_parser, accumulate_attribute);
6233 XML_SetUserData(g_parser, &storage);
6234 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6235 == XML_STATUS_ERROR)
6236 xml_failure(g_parser);
6237 CharData_CheckXMLChars(&storage, expected);
6238 }
6239 END_TEST
6240
START_TEST(test_attr_after_solidus)6241 START_TEST(test_attr_after_solidus) {
6242 const char *text = "<doc attr1='a' / attr2='b'>";
6243
6244 expect_failure(text, XML_ERROR_INVALID_TOKEN, "Misplaced / not faulted");
6245 }
6246 END_TEST
6247
6248 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)6249 accumulate_entity_decl(void *userData, const XML_Char *entityName,
6250 int is_parameter_entity, const XML_Char *value,
6251 int value_length, const XML_Char *base,
6252 const XML_Char *systemId, const XML_Char *publicId,
6253 const XML_Char *notationName) {
6254 CharData *storage = (CharData *)userData;
6255
6256 UNUSED_P(is_parameter_entity);
6257 UNUSED_P(base);
6258 UNUSED_P(systemId);
6259 UNUSED_P(publicId);
6260 UNUSED_P(notationName);
6261 CharData_AppendXMLChars(storage, entityName, -1);
6262 CharData_AppendXMLChars(storage, XCS("="), 1);
6263 CharData_AppendXMLChars(storage, value, value_length);
6264 CharData_AppendXMLChars(storage, XCS("\n"), 1);
6265 }
6266
START_TEST(test_utf16_pe)6267 START_TEST(test_utf16_pe) {
6268 /* <!DOCTYPE doc [
6269 * <!ENTITY % {KHO KHWAI}{CHO CHAN} '<!ELEMENT doc (#PCDATA)>'>
6270 * %{KHO KHWAI}{CHO CHAN};
6271 * ]>
6272 * <doc></doc>
6273 *
6274 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
6275 * and {CHO CHAN} = U+0E08 = 0xe0 0xb8 0x88 in UTF-8
6276 */
6277 const char text[] = "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0\n"
6278 "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \x0e\x04\x0e\x08\0 "
6279 "\0'\0<\0!\0E\0L\0E\0M\0E\0N\0T\0 "
6280 "\0d\0o\0c\0 \0(\0#\0P\0C\0D\0A\0T\0A\0)\0>\0'\0>\0\n"
6281 "\0%\x0e\x04\x0e\x08\0;\0\n"
6282 "\0]\0>\0\n"
6283 "\0<\0d\0o\0c\0>\0<\0/\0d\0o\0c\0>";
6284 #ifdef XML_UNICODE
6285 const XML_Char *expected = XCS("\x0e04\x0e08=<!ELEMENT doc (#PCDATA)>\n");
6286 #else
6287 const XML_Char *expected
6288 = XCS("\xe0\xb8\x84\xe0\xb8\x88=<!ELEMENT doc (#PCDATA)>\n");
6289 #endif
6290 CharData storage;
6291
6292 CharData_Init(&storage);
6293 XML_SetUserData(g_parser, &storage);
6294 XML_SetEntityDeclHandler(g_parser, accumulate_entity_decl);
6295 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6296 == XML_STATUS_ERROR)
6297 xml_failure(g_parser);
6298 CharData_CheckXMLChars(&storage, expected);
6299 }
6300 END_TEST
6301
6302 /* Test that duff attribute description keywords are rejected */
START_TEST(test_bad_attr_desc_keyword)6303 START_TEST(test_bad_attr_desc_keyword) {
6304 const char *text = "<!DOCTYPE doc [\n"
6305 " <!ATTLIST doc attr CDATA #!IMPLIED>\n"
6306 "]>\n"
6307 "<doc />";
6308
6309 expect_failure(text, XML_ERROR_INVALID_TOKEN,
6310 "Bad keyword !IMPLIED not faulted");
6311 }
6312 END_TEST
6313
6314 /* Test that an invalid attribute description keyword consisting of
6315 * UTF-16 characters with their top bytes non-zero are correctly
6316 * faulted
6317 */
START_TEST(test_bad_attr_desc_keyword_utf16)6318 START_TEST(test_bad_attr_desc_keyword_utf16) {
6319 /* <!DOCTYPE d [
6320 * <!ATTLIST d a CDATA #{KHO KHWAI}{CHO CHAN}>
6321 * ]><d/>
6322 *
6323 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
6324 * and {CHO CHAN} = U+0E08 = 0xe0 0xb8 0x88 in UTF-8
6325 */
6326 const char text[]
6327 = "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n"
6328 "\0<\0!\0A\0T\0T\0L\0I\0S\0T\0 \0d\0 \0a\0 \0C\0D\0A\0T\0A\0 "
6329 "\0#\x0e\x04\x0e\x08\0>\0\n"
6330 "\0]\0>\0<\0d\0/\0>";
6331
6332 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6333 != XML_STATUS_ERROR)
6334 fail("Invalid UTF16 attribute keyword not faulted");
6335 if (XML_GetErrorCode(g_parser) != XML_ERROR_SYNTAX)
6336 xml_failure(g_parser);
6337 }
6338 END_TEST
6339
6340 /* Test that invalid syntax in a <!DOCTYPE> is rejected. Do this
6341 * using prefix-encoding (see above) to trigger specific code paths
6342 */
START_TEST(test_bad_doctype)6343 START_TEST(test_bad_doctype) {
6344 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
6345 "<!DOCTYPE doc [ \x80\x44 ]><doc/>";
6346
6347 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
6348 expect_failure(text, XML_ERROR_SYNTAX,
6349 "Invalid bytes in DOCTYPE not faulted");
6350 }
6351 END_TEST
6352
START_TEST(test_bad_doctype_utf8)6353 START_TEST(test_bad_doctype_utf8) {
6354 const char *text = "<!DOCTYPE \xDB\x25"
6355 "doc><doc/>"; // [1101 1011] [<0>010 0101]
6356 expect_failure(text, XML_ERROR_INVALID_TOKEN,
6357 "Invalid UTF-8 in DOCTYPE not faulted");
6358 }
6359 END_TEST
6360
START_TEST(test_bad_doctype_utf16)6361 START_TEST(test_bad_doctype_utf16) {
6362 const char text[] =
6363 /* <!DOCTYPE doc [ \x06f2 ]><doc/>
6364 *
6365 * U+06F2 = EXTENDED ARABIC-INDIC DIGIT TWO, a valid number
6366 * (name character) but not a valid letter (name start character)
6367 */
6368 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0 "
6369 "\x06\xf2"
6370 "\0 \0]\0>\0<\0d\0o\0c\0/\0>";
6371
6372 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6373 != XML_STATUS_ERROR)
6374 fail("Invalid bytes in DOCTYPE not faulted");
6375 if (XML_GetErrorCode(g_parser) != XML_ERROR_SYNTAX)
6376 xml_failure(g_parser);
6377 }
6378 END_TEST
6379
START_TEST(test_bad_doctype_plus)6380 START_TEST(test_bad_doctype_plus) {
6381 const char *text = "<!DOCTYPE 1+ [ <!ENTITY foo 'bar'> ]>\n"
6382 "<1+>&foo;</1+>";
6383
6384 expect_failure(text, XML_ERROR_INVALID_TOKEN,
6385 "'+' in document name not faulted");
6386 }
6387 END_TEST
6388
START_TEST(test_bad_doctype_star)6389 START_TEST(test_bad_doctype_star) {
6390 const char *text = "<!DOCTYPE 1* [ <!ENTITY foo 'bar'> ]>\n"
6391 "<1*>&foo;</1*>";
6392
6393 expect_failure(text, XML_ERROR_INVALID_TOKEN,
6394 "'*' in document name not faulted");
6395 }
6396 END_TEST
6397
START_TEST(test_bad_doctype_query)6398 START_TEST(test_bad_doctype_query) {
6399 const char *text = "<!DOCTYPE 1? [ <!ENTITY foo 'bar'> ]>\n"
6400 "<1?>&foo;</1?>";
6401
6402 expect_failure(text, XML_ERROR_INVALID_TOKEN,
6403 "'?' in document name not faulted");
6404 }
6405 END_TEST
6406
START_TEST(test_unknown_encoding_bad_ignore)6407 START_TEST(test_unknown_encoding_bad_ignore) {
6408 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>"
6409 "<!DOCTYPE doc SYSTEM 'foo'>"
6410 "<doc><e>&entity;</e></doc>";
6411 ExtFaults fault = {"<![IGNORE[<!ELEMENT \xffG (#PCDATA)*>]]>",
6412 "Invalid character not faulted", XCS("prefix-conv"),
6413 XML_ERROR_INVALID_TOKEN};
6414
6415 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
6416 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6417 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
6418 XML_SetUserData(g_parser, &fault);
6419 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
6420 "Bad IGNORE section with unknown encoding not failed");
6421 }
6422 END_TEST
6423
START_TEST(test_entity_in_utf16_be_attr)6424 START_TEST(test_entity_in_utf16_be_attr) {
6425 const char text[] =
6426 /* <e a='ä ä'></e> */
6427 "\0<\0e\0 \0a\0=\0'\0&\0#\0\x32\0\x32\0\x38\0;\0 "
6428 "\0&\0#\0x\0\x30\0\x30\0E\0\x34\0;\0'\0>\0<\0/\0e\0>";
6429 #ifdef XML_UNICODE
6430 const XML_Char *expected = XCS("\x00e4 \x00e4");
6431 #else
6432 const XML_Char *expected = XCS("\xc3\xa4 \xc3\xa4");
6433 #endif
6434 CharData storage;
6435
6436 CharData_Init(&storage);
6437 XML_SetUserData(g_parser, &storage);
6438 XML_SetStartElementHandler(g_parser, accumulate_attribute);
6439 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6440 == XML_STATUS_ERROR)
6441 xml_failure(g_parser);
6442 CharData_CheckXMLChars(&storage, expected);
6443 }
6444 END_TEST
6445
START_TEST(test_entity_in_utf16_le_attr)6446 START_TEST(test_entity_in_utf16_le_attr) {
6447 const char text[] =
6448 /* <e a='ä ä'></e> */
6449 "<\0e\0 \0a\0=\0'\0&\0#\0\x32\0\x32\0\x38\0;\0 \0"
6450 "&\0#\0x\0\x30\0\x30\0E\0\x34\0;\0'\0>\0<\0/\0e\0>\0";
6451 #ifdef XML_UNICODE
6452 const XML_Char *expected = XCS("\x00e4 \x00e4");
6453 #else
6454 const XML_Char *expected = XCS("\xc3\xa4 \xc3\xa4");
6455 #endif
6456 CharData storage;
6457
6458 CharData_Init(&storage);
6459 XML_SetUserData(g_parser, &storage);
6460 XML_SetStartElementHandler(g_parser, accumulate_attribute);
6461 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6462 == XML_STATUS_ERROR)
6463 xml_failure(g_parser);
6464 CharData_CheckXMLChars(&storage, expected);
6465 }
6466 END_TEST
6467
START_TEST(test_entity_public_utf16_be)6468 START_TEST(test_entity_public_utf16_be) {
6469 const char text[] =
6470 /* <!DOCTYPE d [ */
6471 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n"
6472 /* <!ENTITY % e PUBLIC 'foo' 'bar.ent'> */
6473 "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \0e\0 \0P\0U\0B\0L\0I\0C\0 "
6474 "\0'\0f\0o\0o\0'\0 \0'\0b\0a\0r\0.\0e\0n\0t\0'\0>\0\n"
6475 /* %e; */
6476 "\0%\0e\0;\0\n"
6477 /* ]> */
6478 "\0]\0>\0\n"
6479 /* <d>&j;</d> */
6480 "\0<\0d\0>\0&\0j\0;\0<\0/\0d\0>";
6481 ExtTest2 test_data = {/* <!ENTITY j 'baz'> */
6482 "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0j\0 \0'\0b\0a\0z\0'\0>",
6483 34, NULL, NULL, EE_PARSE_NONE};
6484 const XML_Char *expected = XCS("baz");
6485 CharData storage;
6486
6487 CharData_Init(&storage);
6488 test_data.storage = &storage;
6489 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6490 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
6491 XML_SetUserData(g_parser, &test_data);
6492 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
6493 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6494 == XML_STATUS_ERROR)
6495 xml_failure(g_parser);
6496 CharData_CheckXMLChars(&storage, expected);
6497 }
6498 END_TEST
6499
START_TEST(test_entity_public_utf16_le)6500 START_TEST(test_entity_public_utf16_le) {
6501 const char text[] =
6502 /* <!DOCTYPE d [ */
6503 "<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n\0"
6504 /* <!ENTITY % e PUBLIC 'foo' 'bar.ent'> */
6505 "<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \0e\0 \0P\0U\0B\0L\0I\0C\0 \0"
6506 "'\0f\0o\0o\0'\0 \0'\0b\0a\0r\0.\0e\0n\0t\0'\0>\0\n\0"
6507 /* %e; */
6508 "%\0e\0;\0\n\0"
6509 /* ]> */
6510 "]\0>\0\n\0"
6511 /* <d>&j;</d> */
6512 "<\0d\0>\0&\0j\0;\0<\0/\0d\0>\0";
6513 ExtTest2 test_data = {/* <!ENTITY j 'baz'> */
6514 "<\0!\0E\0N\0T\0I\0T\0Y\0 \0j\0 \0'\0b\0a\0z\0'\0>\0",
6515 34, NULL, NULL, EE_PARSE_NONE};
6516 const XML_Char *expected = XCS("baz");
6517 CharData storage;
6518
6519 CharData_Init(&storage);
6520 test_data.storage = &storage;
6521 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6522 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
6523 XML_SetUserData(g_parser, &test_data);
6524 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
6525 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6526 == XML_STATUS_ERROR)
6527 xml_failure(g_parser);
6528 CharData_CheckXMLChars(&storage, expected);
6529 }
6530 END_TEST
6531
6532 /* Test that a doctype with neither an internal nor external subset is
6533 * faulted
6534 */
START_TEST(test_short_doctype)6535 START_TEST(test_short_doctype) {
6536 const char *text = "<!DOCTYPE doc></doc>";
6537 expect_failure(text, XML_ERROR_INVALID_TOKEN,
6538 "DOCTYPE without subset not rejected");
6539 }
6540 END_TEST
6541
START_TEST(test_short_doctype_2)6542 START_TEST(test_short_doctype_2) {
6543 const char *text = "<!DOCTYPE doc PUBLIC></doc>";
6544 expect_failure(text, XML_ERROR_SYNTAX,
6545 "DOCTYPE without Public ID not rejected");
6546 }
6547 END_TEST
6548
START_TEST(test_short_doctype_3)6549 START_TEST(test_short_doctype_3) {
6550 const char *text = "<!DOCTYPE doc SYSTEM></doc>";
6551 expect_failure(text, XML_ERROR_SYNTAX,
6552 "DOCTYPE without System ID not rejected");
6553 }
6554 END_TEST
6555
START_TEST(test_long_doctype)6556 START_TEST(test_long_doctype) {
6557 const char *text = "<!DOCTYPE doc PUBLIC 'foo' 'bar' 'baz'></doc>";
6558 expect_failure(text, XML_ERROR_SYNTAX, "DOCTYPE with extra ID not rejected");
6559 }
6560 END_TEST
6561
START_TEST(test_bad_entity)6562 START_TEST(test_bad_entity) {
6563 const char *text = "<!DOCTYPE doc [\n"
6564 " <!ENTITY foo PUBLIC>\n"
6565 "]>\n"
6566 "<doc/>";
6567 expect_failure(text, XML_ERROR_SYNTAX,
6568 "ENTITY without Public ID is not rejected");
6569 }
6570 END_TEST
6571
6572 /* Test unquoted value is faulted */
START_TEST(test_bad_entity_2)6573 START_TEST(test_bad_entity_2) {
6574 const char *text = "<!DOCTYPE doc [\n"
6575 " <!ENTITY % foo bar>\n"
6576 "]>\n"
6577 "<doc/>";
6578 expect_failure(text, XML_ERROR_SYNTAX,
6579 "ENTITY without Public ID is not rejected");
6580 }
6581 END_TEST
6582
START_TEST(test_bad_entity_3)6583 START_TEST(test_bad_entity_3) {
6584 const char *text = "<!DOCTYPE doc [\n"
6585 " <!ENTITY % foo PUBLIC>\n"
6586 "]>\n"
6587 "<doc/>";
6588 expect_failure(text, XML_ERROR_SYNTAX,
6589 "Parameter ENTITY without Public ID is not rejected");
6590 }
6591 END_TEST
6592
START_TEST(test_bad_entity_4)6593 START_TEST(test_bad_entity_4) {
6594 const char *text = "<!DOCTYPE doc [\n"
6595 " <!ENTITY % foo SYSTEM>\n"
6596 "]>\n"
6597 "<doc/>";
6598 expect_failure(text, XML_ERROR_SYNTAX,
6599 "Parameter ENTITY without Public ID is not rejected");
6600 }
6601 END_TEST
6602
START_TEST(test_bad_notation)6603 START_TEST(test_bad_notation) {
6604 const char *text = "<!DOCTYPE doc [\n"
6605 " <!NOTATION n SYSTEM>\n"
6606 "]>\n"
6607 "<doc/>";
6608 expect_failure(text, XML_ERROR_SYNTAX,
6609 "Notation without System ID is not rejected");
6610 }
6611 END_TEST
6612
6613 /* Test for issue #11, wrongly suppressed default handler */
6614 typedef struct default_check {
6615 const XML_Char *expected;
6616 const int expectedLen;
6617 XML_Bool seen;
6618 } DefaultCheck;
6619
6620 static void XMLCALL
checking_default_handler(void * userData,const XML_Char * s,int len)6621 checking_default_handler(void *userData, const XML_Char *s, int len) {
6622 DefaultCheck *data = (DefaultCheck *)userData;
6623 int i;
6624
6625 for (i = 0; data[i].expected != NULL; i++) {
6626 if (data[i].expectedLen == len
6627 && ! memcmp(data[i].expected, s, len * sizeof(XML_Char))) {
6628 data[i].seen = XML_TRUE;
6629 break;
6630 }
6631 }
6632 }
6633
START_TEST(test_default_doctype_handler)6634 START_TEST(test_default_doctype_handler) {
6635 const char *text = "<!DOCTYPE doc PUBLIC 'pubname' 'test.dtd' [\n"
6636 " <!ENTITY foo 'bar'>\n"
6637 "]>\n"
6638 "<doc>&foo;</doc>";
6639 DefaultCheck test_data[] = {{XCS("'pubname'"), 9, XML_FALSE},
6640 {XCS("'test.dtd'"), 10, XML_FALSE},
6641 {NULL, 0, XML_FALSE}};
6642 int i;
6643
6644 XML_SetUserData(g_parser, &test_data);
6645 XML_SetDefaultHandler(g_parser, checking_default_handler);
6646 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
6647 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6648 == XML_STATUS_ERROR)
6649 xml_failure(g_parser);
6650 for (i = 0; test_data[i].expected != NULL; i++)
6651 if (! test_data[i].seen)
6652 fail("Default handler not run for public !DOCTYPE");
6653 }
6654 END_TEST
6655
START_TEST(test_empty_element_abort)6656 START_TEST(test_empty_element_abort) {
6657 const char *text = "<abort/>";
6658
6659 XML_SetStartElementHandler(g_parser, start_element_suspender);
6660 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6661 != XML_STATUS_ERROR)
6662 fail("Expected to error on abort");
6663 }
6664 END_TEST
6665
6666 /*
6667 * Namespaces tests.
6668 */
6669
6670 static void
namespace_setup(void)6671 namespace_setup(void) {
6672 g_parser = XML_ParserCreateNS(NULL, XCS(' '));
6673 if (g_parser == NULL)
6674 fail("Parser not created.");
6675 }
6676
6677 static void
namespace_teardown(void)6678 namespace_teardown(void) {
6679 basic_teardown();
6680 }
6681
6682 /* Check that an element name and attribute name match the expected values.
6683 The expected values are passed as an array reference of string pointers
6684 provided as the userData argument; the first is the expected
6685 element name, and the second is the expected attribute name.
6686 */
6687 static int triplet_start_flag = XML_FALSE;
6688 static int triplet_end_flag = XML_FALSE;
6689
6690 static void XMLCALL
triplet_start_checker(void * userData,const XML_Char * name,const XML_Char ** atts)6691 triplet_start_checker(void *userData, const XML_Char *name,
6692 const XML_Char **atts) {
6693 XML_Char **elemstr = (XML_Char **)userData;
6694 char buffer[1024];
6695 if (xcstrcmp(elemstr[0], name) != 0) {
6696 sprintf(buffer, "unexpected start string: '%" XML_FMT_STR "'", name);
6697 fail(buffer);
6698 }
6699 if (xcstrcmp(elemstr[1], atts[0]) != 0) {
6700 sprintf(buffer, "unexpected attribute string: '%" XML_FMT_STR "'", atts[0]);
6701 fail(buffer);
6702 }
6703 triplet_start_flag = XML_TRUE;
6704 }
6705
6706 /* Check that the element name passed to the end-element handler matches
6707 the expected value. The expected value is passed as the first element
6708 in an array of strings passed as the userData argument.
6709 */
6710 static void XMLCALL
triplet_end_checker(void * userData,const XML_Char * name)6711 triplet_end_checker(void *userData, const XML_Char *name) {
6712 XML_Char **elemstr = (XML_Char **)userData;
6713 if (xcstrcmp(elemstr[0], name) != 0) {
6714 char buffer[1024];
6715 sprintf(buffer, "unexpected end string: '%" XML_FMT_STR "'", name);
6716 fail(buffer);
6717 }
6718 triplet_end_flag = XML_TRUE;
6719 }
6720
START_TEST(test_return_ns_triplet)6721 START_TEST(test_return_ns_triplet) {
6722 const char *text = "<foo:e xmlns:foo='http://example.org/' bar:a='12'\n"
6723 " xmlns:bar='http://example.org/'>";
6724 const char *epilog = "</foo:e>";
6725 const XML_Char *elemstr[]
6726 = {XCS("http://example.org/ e foo"), XCS("http://example.org/ a bar")};
6727 XML_SetReturnNSTriplet(g_parser, XML_TRUE);
6728 XML_SetUserData(g_parser, (void *)elemstr);
6729 XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
6730 XML_SetNamespaceDeclHandler(g_parser, dummy_start_namespace_decl_handler,
6731 dummy_end_namespace_decl_handler);
6732 triplet_start_flag = XML_FALSE;
6733 triplet_end_flag = XML_FALSE;
6734 dummy_handler_flags = 0;
6735 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
6736 == XML_STATUS_ERROR)
6737 xml_failure(g_parser);
6738 if (! triplet_start_flag)
6739 fail("triplet_start_checker not invoked");
6740 /* Check that unsetting "return triplets" fails while still parsing */
6741 XML_SetReturnNSTriplet(g_parser, XML_FALSE);
6742 if (_XML_Parse_SINGLE_BYTES(g_parser, epilog, (int)strlen(epilog), XML_TRUE)
6743 == XML_STATUS_ERROR)
6744 xml_failure(g_parser);
6745 if (! triplet_end_flag)
6746 fail("triplet_end_checker not invoked");
6747 if (dummy_handler_flags
6748 != (DUMMY_START_NS_DECL_HANDLER_FLAG | DUMMY_END_NS_DECL_HANDLER_FLAG))
6749 fail("Namespace handlers not called");
6750 }
6751 END_TEST
6752
6753 static void XMLCALL
overwrite_start_checker(void * userData,const XML_Char * name,const XML_Char ** atts)6754 overwrite_start_checker(void *userData, const XML_Char *name,
6755 const XML_Char **atts) {
6756 CharData *storage = (CharData *)userData;
6757 CharData_AppendXMLChars(storage, XCS("start "), 6);
6758 CharData_AppendXMLChars(storage, name, -1);
6759 while (*atts != NULL) {
6760 CharData_AppendXMLChars(storage, XCS("\nattribute "), 11);
6761 CharData_AppendXMLChars(storage, *atts, -1);
6762 atts += 2;
6763 }
6764 CharData_AppendXMLChars(storage, XCS("\n"), 1);
6765 }
6766
6767 static void XMLCALL
overwrite_end_checker(void * userData,const XML_Char * name)6768 overwrite_end_checker(void *userData, const XML_Char *name) {
6769 CharData *storage = (CharData *)userData;
6770 CharData_AppendXMLChars(storage, XCS("end "), 4);
6771 CharData_AppendXMLChars(storage, name, -1);
6772 CharData_AppendXMLChars(storage, XCS("\n"), 1);
6773 }
6774
6775 static void
run_ns_tagname_overwrite_test(const char * text,const XML_Char * result)6776 run_ns_tagname_overwrite_test(const char *text, const XML_Char *result) {
6777 CharData storage;
6778 CharData_Init(&storage);
6779 XML_SetUserData(g_parser, &storage);
6780 XML_SetElementHandler(g_parser, overwrite_start_checker,
6781 overwrite_end_checker);
6782 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6783 == XML_STATUS_ERROR)
6784 xml_failure(g_parser);
6785 CharData_CheckXMLChars(&storage, result);
6786 }
6787
6788 /* Regression test for SF bug #566334. */
START_TEST(test_ns_tagname_overwrite)6789 START_TEST(test_ns_tagname_overwrite) {
6790 const char *text = "<n:e xmlns:n='http://example.org/'>\n"
6791 " <n:f n:attr='foo'/>\n"
6792 " <n:g n:attr2='bar'/>\n"
6793 "</n:e>";
6794 const XML_Char *result = XCS("start http://example.org/ e\n")
6795 XCS("start http://example.org/ f\n")
6796 XCS("attribute http://example.org/ attr\n")
6797 XCS("end http://example.org/ f\n")
6798 XCS("start http://example.org/ g\n")
6799 XCS("attribute http://example.org/ attr2\n")
6800 XCS("end http://example.org/ g\n")
6801 XCS("end http://example.org/ e\n");
6802 run_ns_tagname_overwrite_test(text, result);
6803 }
6804 END_TEST
6805
6806 /* Regression test for SF bug #566334. */
START_TEST(test_ns_tagname_overwrite_triplet)6807 START_TEST(test_ns_tagname_overwrite_triplet) {
6808 const char *text = "<n:e xmlns:n='http://example.org/'>\n"
6809 " <n:f n:attr='foo'/>\n"
6810 " <n:g n:attr2='bar'/>\n"
6811 "</n:e>";
6812 const XML_Char *result = XCS("start http://example.org/ e n\n")
6813 XCS("start http://example.org/ f n\n")
6814 XCS("attribute http://example.org/ attr n\n")
6815 XCS("end http://example.org/ f n\n")
6816 XCS("start http://example.org/ g n\n")
6817 XCS("attribute http://example.org/ attr2 n\n")
6818 XCS("end http://example.org/ g n\n")
6819 XCS("end http://example.org/ e n\n");
6820 XML_SetReturnNSTriplet(g_parser, XML_TRUE);
6821 run_ns_tagname_overwrite_test(text, result);
6822 }
6823 END_TEST
6824
6825 /* Regression test for SF bug #620343. */
6826 static void XMLCALL
start_element_fail(void * userData,const XML_Char * name,const XML_Char ** atts)6827 start_element_fail(void *userData, const XML_Char *name,
6828 const XML_Char **atts) {
6829 UNUSED_P(userData);
6830 UNUSED_P(name);
6831 UNUSED_P(atts);
6832
6833 /* We should never get here. */
6834 fail("should never reach start_element_fail()");
6835 }
6836
6837 static void XMLCALL
start_ns_clearing_start_element(void * userData,const XML_Char * prefix,const XML_Char * uri)6838 start_ns_clearing_start_element(void *userData, const XML_Char *prefix,
6839 const XML_Char *uri) {
6840 UNUSED_P(prefix);
6841 UNUSED_P(uri);
6842 XML_SetStartElementHandler((XML_Parser)userData, NULL);
6843 }
6844
START_TEST(test_start_ns_clears_start_element)6845 START_TEST(test_start_ns_clears_start_element) {
6846 /* This needs to use separate start/end tags; using the empty tag
6847 syntax doesn't cause the problematic path through Expat to be
6848 taken.
6849 */
6850 const char *text = "<e xmlns='http://example.org/'></e>";
6851
6852 XML_SetStartElementHandler(g_parser, start_element_fail);
6853 XML_SetStartNamespaceDeclHandler(g_parser, start_ns_clearing_start_element);
6854 XML_SetEndNamespaceDeclHandler(g_parser, dummy_end_namespace_decl_handler);
6855 XML_UseParserAsHandlerArg(g_parser);
6856 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6857 == XML_STATUS_ERROR)
6858 xml_failure(g_parser);
6859 }
6860 END_TEST
6861
6862 /* Regression test for SF bug #616863. */
6863 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)6864 external_entity_handler(XML_Parser parser, const XML_Char *context,
6865 const XML_Char *base, const XML_Char *systemId,
6866 const XML_Char *publicId) {
6867 intptr_t callno = 1 + (intptr_t)XML_GetUserData(parser);
6868 const char *text;
6869 XML_Parser p2;
6870
6871 UNUSED_P(base);
6872 UNUSED_P(systemId);
6873 UNUSED_P(publicId);
6874 if (callno == 1)
6875 text = ("<!ELEMENT doc (e+)>\n"
6876 "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
6877 "<!ELEMENT e EMPTY>\n");
6878 else
6879 text = ("<?xml version='1.0' encoding='us-ascii'?>"
6880 "<e/>");
6881
6882 XML_SetUserData(parser, (void *)callno);
6883 p2 = XML_ExternalEntityParserCreate(parser, context, NULL);
6884 if (_XML_Parse_SINGLE_BYTES(p2, text, (int)strlen(text), XML_TRUE)
6885 == XML_STATUS_ERROR) {
6886 xml_failure(p2);
6887 return XML_STATUS_ERROR;
6888 }
6889 XML_ParserFree(p2);
6890 return XML_STATUS_OK;
6891 }
6892
START_TEST(test_default_ns_from_ext_subset_and_ext_ge)6893 START_TEST(test_default_ns_from_ext_subset_and_ext_ge) {
6894 const char *text = "<?xml version='1.0'?>\n"
6895 "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n"
6896 " <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n"
6897 "]>\n"
6898 "<doc xmlns='http://example.org/ns1'>\n"
6899 "&en;\n"
6900 "</doc>";
6901
6902 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6903 XML_SetExternalEntityRefHandler(g_parser, external_entity_handler);
6904 /* We actually need to set this handler to tickle this bug. */
6905 XML_SetStartElementHandler(g_parser, dummy_start_element);
6906 XML_SetUserData(g_parser, NULL);
6907 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6908 == XML_STATUS_ERROR)
6909 xml_failure(g_parser);
6910 }
6911 END_TEST
6912
6913 /* Regression test #1 for SF bug #673791. */
START_TEST(test_ns_prefix_with_empty_uri_1)6914 START_TEST(test_ns_prefix_with_empty_uri_1) {
6915 const char *text = "<doc xmlns:prefix='http://example.org/'>\n"
6916 " <e xmlns:prefix=''/>\n"
6917 "</doc>";
6918
6919 expect_failure(text, XML_ERROR_UNDECLARING_PREFIX,
6920 "Did not report re-setting namespace"
6921 " URI with prefix to ''.");
6922 }
6923 END_TEST
6924
6925 /* Regression test #2 for SF bug #673791. */
START_TEST(test_ns_prefix_with_empty_uri_2)6926 START_TEST(test_ns_prefix_with_empty_uri_2) {
6927 const char *text = "<?xml version='1.0'?>\n"
6928 "<docelem xmlns:pre=''/>";
6929
6930 expect_failure(text, XML_ERROR_UNDECLARING_PREFIX,
6931 "Did not report setting namespace URI with prefix to ''.");
6932 }
6933 END_TEST
6934
6935 /* Regression test #3 for SF bug #673791. */
START_TEST(test_ns_prefix_with_empty_uri_3)6936 START_TEST(test_ns_prefix_with_empty_uri_3) {
6937 const char *text = "<!DOCTYPE doc [\n"
6938 " <!ELEMENT doc EMPTY>\n"
6939 " <!ATTLIST doc\n"
6940 " xmlns:prefix CDATA ''>\n"
6941 "]>\n"
6942 "<doc/>";
6943
6944 expect_failure(text, XML_ERROR_UNDECLARING_PREFIX,
6945 "Didn't report attr default setting NS w/ prefix to ''.");
6946 }
6947 END_TEST
6948
6949 /* Regression test #4 for SF bug #673791. */
START_TEST(test_ns_prefix_with_empty_uri_4)6950 START_TEST(test_ns_prefix_with_empty_uri_4) {
6951 const char *text = "<!DOCTYPE doc [\n"
6952 " <!ELEMENT prefix:doc EMPTY>\n"
6953 " <!ATTLIST prefix:doc\n"
6954 " xmlns:prefix CDATA 'http://example.org/'>\n"
6955 "]>\n"
6956 "<prefix:doc/>";
6957 /* Packaged info expected by the end element handler;
6958 the weird structuring lets us re-use the triplet_end_checker()
6959 function also used for another test. */
6960 const XML_Char *elemstr[] = {XCS("http://example.org/ doc prefix")};
6961 XML_SetReturnNSTriplet(g_parser, XML_TRUE);
6962 XML_SetUserData(g_parser, (void *)elemstr);
6963 XML_SetEndElementHandler(g_parser, triplet_end_checker);
6964 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6965 == XML_STATUS_ERROR)
6966 xml_failure(g_parser);
6967 }
6968 END_TEST
6969
6970 /* Test with non-xmlns prefix */
START_TEST(test_ns_unbound_prefix)6971 START_TEST(test_ns_unbound_prefix) {
6972 const char *text = "<!DOCTYPE doc [\n"
6973 " <!ELEMENT prefix:doc EMPTY>\n"
6974 " <!ATTLIST prefix:doc\n"
6975 " notxmlns:prefix CDATA 'http://example.org/'>\n"
6976 "]>\n"
6977 "<prefix:doc/>";
6978
6979 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6980 != XML_STATUS_ERROR)
6981 fail("Unbound prefix incorrectly passed");
6982 if (XML_GetErrorCode(g_parser) != XML_ERROR_UNBOUND_PREFIX)
6983 xml_failure(g_parser);
6984 }
6985 END_TEST
6986
START_TEST(test_ns_default_with_empty_uri)6987 START_TEST(test_ns_default_with_empty_uri) {
6988 const char *text = "<doc xmlns='http://example.org/'>\n"
6989 " <e xmlns=''/>\n"
6990 "</doc>";
6991 /* Add some handlers to exercise extra code paths */
6992 XML_SetStartNamespaceDeclHandler(g_parser,
6993 dummy_start_namespace_decl_handler);
6994 XML_SetEndNamespaceDeclHandler(g_parser, dummy_end_namespace_decl_handler);
6995 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6996 == XML_STATUS_ERROR)
6997 xml_failure(g_parser);
6998 }
6999 END_TEST
7000
7001 /* Regression test for SF bug #692964: two prefixes for one namespace. */
START_TEST(test_ns_duplicate_attrs_diff_prefixes)7002 START_TEST(test_ns_duplicate_attrs_diff_prefixes) {
7003 const char *text = "<doc xmlns:a='http://example.org/a'\n"
7004 " xmlns:b='http://example.org/a'\n"
7005 " a:a='v' b:a='v' />";
7006 expect_failure(text, XML_ERROR_DUPLICATE_ATTRIBUTE,
7007 "did not report multiple attributes with same URI+name");
7008 }
7009 END_TEST
7010
START_TEST(test_ns_duplicate_hashes)7011 START_TEST(test_ns_duplicate_hashes) {
7012 /* The hash of an attribute is calculated as the hash of its URI
7013 * concatenated with a space followed by its name (after the
7014 * colon). We wish to generate attributes with the same hash
7015 * value modulo the attribute table size so that we can check that
7016 * the attribute hash table works correctly. The attribute hash
7017 * table size will be the smallest power of two greater than the
7018 * number of attributes, but at least eight. There is
7019 * unfortunately no programmatic way of getting the hash or the
7020 * table size at user level, but the test code coverage percentage
7021 * will drop if the hashes cease to point to the same row.
7022 *
7023 * The cunning plan is to have few enough attributes to have a
7024 * reliable table size of 8, and have the single letter attribute
7025 * names be 8 characters apart, producing a hash which will be the
7026 * same modulo 8.
7027 */
7028 const char *text = "<doc xmlns:a='http://example.org/a'\n"
7029 " a:a='v' a:i='w' />";
7030 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7031 == XML_STATUS_ERROR)
7032 xml_failure(g_parser);
7033 }
7034 END_TEST
7035
7036 /* Regression test for SF bug #695401: unbound prefix. */
START_TEST(test_ns_unbound_prefix_on_attribute)7037 START_TEST(test_ns_unbound_prefix_on_attribute) {
7038 const char *text = "<doc a:attr=''/>";
7039 expect_failure(text, XML_ERROR_UNBOUND_PREFIX,
7040 "did not report unbound prefix on attribute");
7041 }
7042 END_TEST
7043
7044 /* Regression test for SF bug #695401: unbound prefix. */
START_TEST(test_ns_unbound_prefix_on_element)7045 START_TEST(test_ns_unbound_prefix_on_element) {
7046 const char *text = "<a:doc/>";
7047 expect_failure(text, XML_ERROR_UNBOUND_PREFIX,
7048 "did not report unbound prefix on element");
7049 }
7050 END_TEST
7051
7052 /* Test that the parsing status is correctly reset by XML_ParserReset().
7053 * We usE test_return_ns_triplet() for our example parse to improve
7054 * coverage of tidying up code executed.
7055 */
START_TEST(test_ns_parser_reset)7056 START_TEST(test_ns_parser_reset) {
7057 XML_ParsingStatus status;
7058
7059 XML_GetParsingStatus(g_parser, &status);
7060 if (status.parsing != XML_INITIALIZED)
7061 fail("parsing status doesn't start INITIALIZED");
7062 test_return_ns_triplet();
7063 XML_GetParsingStatus(g_parser, &status);
7064 if (status.parsing != XML_FINISHED)
7065 fail("parsing status doesn't end FINISHED");
7066 XML_ParserReset(g_parser, NULL);
7067 XML_GetParsingStatus(g_parser, &status);
7068 if (status.parsing != XML_INITIALIZED)
7069 fail("parsing status doesn't reset to INITIALIZED");
7070 }
7071 END_TEST
7072
7073 /* Test that long element names with namespaces are handled correctly */
START_TEST(test_ns_long_element)7074 START_TEST(test_ns_long_element) {
7075 const char *text
7076 = "<foo:thisisalongenoughelementnametotriggerareallocation\n"
7077 " xmlns:foo='http://example.org/' bar:a='12'\n"
7078 " xmlns:bar='http://example.org/'>"
7079 "</foo:thisisalongenoughelementnametotriggerareallocation>";
7080 const XML_Char *elemstr[]
7081 = {XCS("http://example.org/")
7082 XCS(" thisisalongenoughelementnametotriggerareallocation foo"),
7083 XCS("http://example.org/ a bar")};
7084
7085 XML_SetReturnNSTriplet(g_parser, XML_TRUE);
7086 XML_SetUserData(g_parser, (void *)elemstr);
7087 XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
7088 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7089 == XML_STATUS_ERROR)
7090 xml_failure(g_parser);
7091 }
7092 END_TEST
7093
7094 /* Test mixed population of prefixed and unprefixed attributes */
START_TEST(test_ns_mixed_prefix_atts)7095 START_TEST(test_ns_mixed_prefix_atts) {
7096 const char *text = "<e a='12' bar:b='13'\n"
7097 " xmlns:bar='http://example.org/'>"
7098 "</e>";
7099
7100 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7101 == XML_STATUS_ERROR)
7102 xml_failure(g_parser);
7103 }
7104 END_TEST
7105
7106 /* Test having a long namespaced element name inside a short one.
7107 * This exercises some internal buffer reallocation that is shared
7108 * across elements with the same namespace URI.
7109 */
START_TEST(test_ns_extend_uri_buffer)7110 START_TEST(test_ns_extend_uri_buffer) {
7111 const char *text = "<foo:e xmlns:foo='http://example.org/'>"
7112 " <foo:thisisalongenoughnametotriggerallocationaction"
7113 " foo:a='12' />"
7114 "</foo:e>";
7115 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7116 == XML_STATUS_ERROR)
7117 xml_failure(g_parser);
7118 }
7119 END_TEST
7120
7121 /* Test that xmlns is correctly rejected as an attribute in the xmlns
7122 * namespace, but not in other namespaces
7123 */
START_TEST(test_ns_reserved_attributes)7124 START_TEST(test_ns_reserved_attributes) {
7125 const char *text1
7126 = "<foo:e xmlns:foo='http://example.org/' xmlns:xmlns='12' />";
7127 const char *text2
7128 = "<foo:e xmlns:foo='http://example.org/' foo:xmlns='12' />";
7129 expect_failure(text1, XML_ERROR_RESERVED_PREFIX_XMLNS,
7130 "xmlns not rejected as an attribute");
7131 XML_ParserReset(g_parser, NULL);
7132 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
7133 == XML_STATUS_ERROR)
7134 xml_failure(g_parser);
7135 }
7136 END_TEST
7137
7138 /* Test more reserved attributes */
START_TEST(test_ns_reserved_attributes_2)7139 START_TEST(test_ns_reserved_attributes_2) {
7140 const char *text1 = "<foo:e xmlns:foo='http://example.org/'"
7141 " xmlns:xml='http://example.org/' />";
7142 const char *text2
7143 = "<foo:e xmlns:foo='http://www.w3.org/XML/1998/namespace' />";
7144 const char *text3 = "<foo:e xmlns:foo='http://www.w3.org/2000/xmlns/' />";
7145
7146 expect_failure(text1, XML_ERROR_RESERVED_PREFIX_XML,
7147 "xml not rejected as an attribute");
7148 XML_ParserReset(g_parser, NULL);
7149 expect_failure(text2, XML_ERROR_RESERVED_NAMESPACE_URI,
7150 "Use of w3.org URL not faulted");
7151 XML_ParserReset(g_parser, NULL);
7152 expect_failure(text3, XML_ERROR_RESERVED_NAMESPACE_URI,
7153 "Use of w3.org xmlns URL not faulted");
7154 }
7155 END_TEST
7156
7157 /* Test string pool handling of namespace names of 2048 characters */
7158 /* Exercises a particular string pool growth path */
START_TEST(test_ns_extremely_long_prefix)7159 START_TEST(test_ns_extremely_long_prefix) {
7160 /* C99 compilers are only required to support 4095-character
7161 * strings, so the following needs to be split in two to be safe
7162 * for all compilers.
7163 */
7164 const char *text1
7165 = "<doc "
7166 /* 64 character on each line */
7167 /* ...gives a total length of 2048 */
7168 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7169 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7170 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7171 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7172 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7173 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
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 ":a='12'";
7201 const char *text2
7202 = " xmlns:"
7203 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7204 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7205 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7206 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7207 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7208 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7209 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7210 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7211 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7212 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7213 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7214 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7215 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7216 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7217 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7218 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7219 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7220 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7221 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7222 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7223 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7224 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7225 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7226 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7227 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7228 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7229 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7230 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7231 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7232 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7233 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7234 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7235 "='foo'\n>"
7236 "</doc>";
7237
7238 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
7239 == XML_STATUS_ERROR)
7240 xml_failure(g_parser);
7241 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
7242 == XML_STATUS_ERROR)
7243 xml_failure(g_parser);
7244 }
7245 END_TEST
7246
7247 /* Test unknown encoding handlers in namespace setup */
START_TEST(test_ns_unknown_encoding_success)7248 START_TEST(test_ns_unknown_encoding_success) {
7249 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
7250 "<foo:e xmlns:foo='http://example.org/'>Hi</foo:e>";
7251
7252 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
7253 run_character_check(text, XCS("Hi"));
7254 }
7255 END_TEST
7256
7257 /* Test that too many colons are rejected */
START_TEST(test_ns_double_colon)7258 START_TEST(test_ns_double_colon) {
7259 const char *text = "<foo:e xmlns:foo='http://example.org/' foo:a:b='bar' />";
7260 const enum XML_Status status
7261 = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE);
7262 #ifdef XML_NS
7263 if ((status == XML_STATUS_OK)
7264 || (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)) {
7265 fail("Double colon in attribute name not faulted"
7266 " (despite active namespace support)");
7267 }
7268 #else
7269 if (status != XML_STATUS_OK) {
7270 fail("Double colon in attribute name faulted"
7271 " (despite inactive namespace support");
7272 }
7273 #endif
7274 }
7275 END_TEST
7276
START_TEST(test_ns_double_colon_element)7277 START_TEST(test_ns_double_colon_element) {
7278 const char *text = "<foo:bar:e xmlns:foo='http://example.org/' />";
7279 const enum XML_Status status
7280 = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE);
7281 #ifdef XML_NS
7282 if ((status == XML_STATUS_OK)
7283 || (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)) {
7284 fail("Double colon in element name not faulted"
7285 " (despite active namespace support)");
7286 }
7287 #else
7288 if (status != XML_STATUS_OK) {
7289 fail("Double colon in element name faulted"
7290 " (despite inactive namespace support");
7291 }
7292 #endif
7293 }
7294 END_TEST
7295
7296 /* Test that non-name characters after a colon are rejected */
START_TEST(test_ns_bad_attr_leafname)7297 START_TEST(test_ns_bad_attr_leafname) {
7298 const char *text = "<foo:e xmlns:foo='http://example.org/' foo:?ar='baz' />";
7299
7300 expect_failure(text, XML_ERROR_INVALID_TOKEN,
7301 "Invalid character in leafname not faulted");
7302 }
7303 END_TEST
7304
START_TEST(test_ns_bad_element_leafname)7305 START_TEST(test_ns_bad_element_leafname) {
7306 const char *text = "<foo:?oc xmlns:foo='http://example.org/' />";
7307
7308 expect_failure(text, XML_ERROR_INVALID_TOKEN,
7309 "Invalid character in element leafname not faulted");
7310 }
7311 END_TEST
7312
7313 /* Test high-byte-set UTF-16 characters are valid in a leafname */
START_TEST(test_ns_utf16_leafname)7314 START_TEST(test_ns_utf16_leafname) {
7315 const char text[] =
7316 /* <n:e xmlns:n='URI' n:{KHO KHWAI}='a' />
7317 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
7318 */
7319 "<\0n\0:\0e\0 \0x\0m\0l\0n\0s\0:\0n\0=\0'\0U\0R\0I\0'\0 \0"
7320 "n\0:\0\x04\x0e=\0'\0a\0'\0 \0/\0>\0";
7321 const XML_Char *expected = XCS("a");
7322 CharData storage;
7323
7324 CharData_Init(&storage);
7325 XML_SetStartElementHandler(g_parser, accumulate_attribute);
7326 XML_SetUserData(g_parser, &storage);
7327 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
7328 == XML_STATUS_ERROR)
7329 xml_failure(g_parser);
7330 CharData_CheckXMLChars(&storage, expected);
7331 }
7332 END_TEST
7333
START_TEST(test_ns_utf16_element_leafname)7334 START_TEST(test_ns_utf16_element_leafname) {
7335 const char text[] =
7336 /* <n:{KHO KHWAI} xmlns:n='URI'/>
7337 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
7338 */
7339 "\0<\0n\0:\x0e\x04\0 \0x\0m\0l\0n\0s\0:\0n\0=\0'\0U\0R\0I\0'\0/\0>";
7340 #ifdef XML_UNICODE
7341 const XML_Char *expected = XCS("URI \x0e04");
7342 #else
7343 const XML_Char *expected = XCS("URI \xe0\xb8\x84");
7344 #endif
7345 CharData storage;
7346
7347 CharData_Init(&storage);
7348 XML_SetStartElementHandler(g_parser, start_element_event_handler);
7349 XML_SetUserData(g_parser, &storage);
7350 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
7351 == XML_STATUS_ERROR)
7352 xml_failure(g_parser);
7353 CharData_CheckXMLChars(&storage, expected);
7354 }
7355 END_TEST
7356
START_TEST(test_ns_utf16_doctype)7357 START_TEST(test_ns_utf16_doctype) {
7358 const char text[] =
7359 /* <!DOCTYPE foo:{KHO KHWAI} [ <!ENTITY bar 'baz'> ]>\n
7360 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
7361 */
7362 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0f\0o\0o\0:\x0e\x04\0 "
7363 "\0[\0 \0<\0!\0E\0N\0T\0I\0T\0Y\0 \0b\0a\0r\0 \0'\0b\0a\0z\0'\0>\0 "
7364 "\0]\0>\0\n"
7365 /* <foo:{KHO KHWAI} xmlns:foo='URI'>&bar;</foo:{KHO KHWAI}> */
7366 "\0<\0f\0o\0o\0:\x0e\x04\0 "
7367 "\0x\0m\0l\0n\0s\0:\0f\0o\0o\0=\0'\0U\0R\0I\0'\0>"
7368 "\0&\0b\0a\0r\0;"
7369 "\0<\0/\0f\0o\0o\0:\x0e\x04\0>";
7370 #ifdef XML_UNICODE
7371 const XML_Char *expected = XCS("URI \x0e04");
7372 #else
7373 const XML_Char *expected = XCS("URI \xe0\xb8\x84");
7374 #endif
7375 CharData storage;
7376
7377 CharData_Init(&storage);
7378 XML_SetUserData(g_parser, &storage);
7379 XML_SetStartElementHandler(g_parser, start_element_event_handler);
7380 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
7381 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
7382 == XML_STATUS_ERROR)
7383 xml_failure(g_parser);
7384 CharData_CheckXMLChars(&storage, expected);
7385 }
7386 END_TEST
7387
START_TEST(test_ns_invalid_doctype)7388 START_TEST(test_ns_invalid_doctype) {
7389 const char *text = "<!DOCTYPE foo:!bad [ <!ENTITY bar 'baz' ]>\n"
7390 "<foo:!bad>&bar;</foo:!bad>";
7391
7392 expect_failure(text, XML_ERROR_INVALID_TOKEN,
7393 "Invalid character in document local name not faulted");
7394 }
7395 END_TEST
7396
START_TEST(test_ns_double_colon_doctype)7397 START_TEST(test_ns_double_colon_doctype) {
7398 const char *text = "<!DOCTYPE foo:a:doc [ <!ENTITY bar 'baz' ]>\n"
7399 "<foo:a:doc>&bar;</foo:a:doc>";
7400
7401 expect_failure(text, XML_ERROR_SYNTAX,
7402 "Double colon in document name not faulted");
7403 }
7404 END_TEST
7405
START_TEST(test_ns_separator_in_uri)7406 START_TEST(test_ns_separator_in_uri) {
7407 struct test_case {
7408 enum XML_Status expectedStatus;
7409 const char *doc;
7410 };
7411 struct test_case cases[] = {
7412 {XML_STATUS_OK, "<doc xmlns='one_two' />"},
7413 {XML_STATUS_ERROR, "<doc xmlns='one
two' />"},
7414 };
7415
7416 size_t i = 0;
7417 size_t failCount = 0;
7418 for (; i < sizeof(cases) / sizeof(cases[0]); i++) {
7419 XML_Parser parser = XML_ParserCreateNS(NULL, '\n');
7420 XML_SetElementHandler(parser, dummy_start_element, dummy_end_element);
7421 if (XML_Parse(parser, cases[i].doc, (int)strlen(cases[i].doc),
7422 /*isFinal*/ XML_TRUE)
7423 != cases[i].expectedStatus) {
7424 failCount++;
7425 }
7426 XML_ParserFree(parser);
7427 }
7428
7429 if (failCount) {
7430 fail("Namespace separator handling is broken");
7431 }
7432 }
7433 END_TEST
7434
7435 /* Control variable; the number of times duff_allocator() will successfully
7436 * allocate */
7437 #define ALLOC_ALWAYS_SUCCEED (-1)
7438 #define REALLOC_ALWAYS_SUCCEED (-1)
7439
7440 static intptr_t allocation_count = ALLOC_ALWAYS_SUCCEED;
7441 static intptr_t reallocation_count = REALLOC_ALWAYS_SUCCEED;
7442
7443 /* Crocked allocator for allocation failure tests */
7444 static void *
duff_allocator(size_t size)7445 duff_allocator(size_t size) {
7446 if (allocation_count == 0)
7447 return NULL;
7448 if (allocation_count != ALLOC_ALWAYS_SUCCEED)
7449 allocation_count--;
7450 return malloc(size);
7451 }
7452
7453 /* Crocked reallocator for allocation failure tests */
7454 static void *
duff_reallocator(void * ptr,size_t size)7455 duff_reallocator(void *ptr, size_t size) {
7456 if (reallocation_count == 0)
7457 return NULL;
7458 if (reallocation_count != REALLOC_ALWAYS_SUCCEED)
7459 reallocation_count--;
7460 return realloc(ptr, size);
7461 }
7462
7463 /* Test that a failure to allocate the parser structure fails gracefully */
START_TEST(test_misc_alloc_create_parser)7464 START_TEST(test_misc_alloc_create_parser) {
7465 XML_Memory_Handling_Suite memsuite = {duff_allocator, realloc, free};
7466 unsigned int i;
7467 const unsigned int max_alloc_count = 10;
7468
7469 /* Something this simple shouldn't need more than 10 allocations */
7470 for (i = 0; i < max_alloc_count; i++) {
7471 allocation_count = i;
7472 g_parser = XML_ParserCreate_MM(NULL, &memsuite, NULL);
7473 if (g_parser != NULL)
7474 break;
7475 }
7476 if (i == 0)
7477 fail("Parser unexpectedly ignored failing allocator");
7478 else if (i == max_alloc_count)
7479 fail("Parser not created with max allocation count");
7480 }
7481 END_TEST
7482
7483 /* Test memory allocation failures for a parser with an encoding */
START_TEST(test_misc_alloc_create_parser_with_encoding)7484 START_TEST(test_misc_alloc_create_parser_with_encoding) {
7485 XML_Memory_Handling_Suite memsuite = {duff_allocator, realloc, free};
7486 unsigned int i;
7487 const unsigned int max_alloc_count = 10;
7488
7489 /* Try several levels of allocation */
7490 for (i = 0; i < max_alloc_count; i++) {
7491 allocation_count = i;
7492 g_parser = XML_ParserCreate_MM(XCS("us-ascii"), &memsuite, NULL);
7493 if (g_parser != NULL)
7494 break;
7495 }
7496 if (i == 0)
7497 fail("Parser ignored failing allocator");
7498 else if (i == max_alloc_count)
7499 fail("Parser not created with max allocation count");
7500 }
7501 END_TEST
7502
7503 /* Test that freeing a NULL parser doesn't cause an explosion.
7504 * (Not actually tested anywhere else)
7505 */
START_TEST(test_misc_null_parser)7506 START_TEST(test_misc_null_parser) {
7507 XML_ParserFree(NULL);
7508 }
7509 END_TEST
7510
7511 /* Test that XML_ErrorString rejects out-of-range codes */
START_TEST(test_misc_error_string)7512 START_TEST(test_misc_error_string) {
7513 if (XML_ErrorString((enum XML_Error) - 1) != NULL)
7514 fail("Negative error code not rejected");
7515 if (XML_ErrorString((enum XML_Error)100) != NULL)
7516 fail("Large error code not rejected");
7517 }
7518 END_TEST
7519
7520 /* Test the version information is consistent */
7521
7522 /* Since we are working in XML_LChars (potentially 16-bits), we
7523 * can't use the standard C library functions for character
7524 * manipulation and have to roll our own.
7525 */
7526 static int
parse_version(const XML_LChar * version_text,XML_Expat_Version * version_struct)7527 parse_version(const XML_LChar *version_text,
7528 XML_Expat_Version *version_struct) {
7529 if (! version_text)
7530 return XML_FALSE;
7531
7532 while (*version_text != 0x00) {
7533 if (*version_text >= ASCII_0 && *version_text <= ASCII_9)
7534 break;
7535 version_text++;
7536 }
7537 if (*version_text == 0x00)
7538 return XML_FALSE;
7539
7540 /* version_struct->major = strtoul(version_text, 10, &version_text) */
7541 version_struct->major = 0;
7542 while (*version_text >= ASCII_0 && *version_text <= ASCII_9) {
7543 version_struct->major
7544 = 10 * version_struct->major + (*version_text++ - ASCII_0);
7545 }
7546 if (*version_text++ != ASCII_PERIOD)
7547 return XML_FALSE;
7548
7549 /* Now for the minor version number */
7550 version_struct->minor = 0;
7551 while (*version_text >= ASCII_0 && *version_text <= ASCII_9) {
7552 version_struct->minor
7553 = 10 * version_struct->minor + (*version_text++ - ASCII_0);
7554 }
7555 if (*version_text++ != ASCII_PERIOD)
7556 return XML_FALSE;
7557
7558 /* Finally the micro version number */
7559 version_struct->micro = 0;
7560 while (*version_text >= ASCII_0 && *version_text <= ASCII_9) {
7561 version_struct->micro
7562 = 10 * version_struct->micro + (*version_text++ - ASCII_0);
7563 }
7564 if (*version_text != 0x00)
7565 return XML_FALSE;
7566 return XML_TRUE;
7567 }
7568
7569 static int
versions_equal(const XML_Expat_Version * first,const XML_Expat_Version * second)7570 versions_equal(const XML_Expat_Version *first,
7571 const XML_Expat_Version *second) {
7572 return (first->major == second->major && first->minor == second->minor
7573 && first->micro == second->micro);
7574 }
7575
START_TEST(test_misc_version)7576 START_TEST(test_misc_version) {
7577 XML_Expat_Version read_version = XML_ExpatVersionInfo();
7578 /* Silence compiler warning with the following assignment */
7579 XML_Expat_Version parsed_version = {0, 0, 0};
7580 const XML_LChar *version_text = XML_ExpatVersion();
7581
7582 if (version_text == NULL)
7583 fail("Could not obtain version text");
7584 assert(version_text != NULL);
7585 if (! parse_version(version_text, &parsed_version))
7586 fail("Unable to parse version text");
7587 if (! versions_equal(&read_version, &parsed_version))
7588 fail("Version mismatch");
7589
7590 #if ! defined(XML_UNICODE) || defined(XML_UNICODE_WCHAR_T)
7591 if (xcstrcmp(version_text, XCS("expat_2.4.6"))) /* needs bump on releases */
7592 fail("XML_*_VERSION in expat.h out of sync?\n");
7593 #else
7594 /* If we have XML_UNICODE defined but not XML_UNICODE_WCHAR_T
7595 * then XML_LChar is defined as char, for some reason.
7596 */
7597 if (strcmp(version_text, "expat_2.2.5")) /* needs bump on releases */
7598 fail("XML_*_VERSION in expat.h out of sync?\n");
7599 #endif /* ! defined(XML_UNICODE) || defined(XML_UNICODE_WCHAR_T) */
7600 }
7601 END_TEST
7602
7603 /* Test feature information */
START_TEST(test_misc_features)7604 START_TEST(test_misc_features) {
7605 const XML_Feature *features = XML_GetFeatureList();
7606
7607 /* Prevent problems with double-freeing parsers */
7608 g_parser = NULL;
7609 if (features == NULL) {
7610 fail("Failed to get feature information");
7611 } else {
7612 /* Loop through the features checking what we can */
7613 while (features->feature != XML_FEATURE_END) {
7614 switch (features->feature) {
7615 case XML_FEATURE_SIZEOF_XML_CHAR:
7616 if (features->value != sizeof(XML_Char))
7617 fail("Incorrect size of XML_Char");
7618 break;
7619 case XML_FEATURE_SIZEOF_XML_LCHAR:
7620 if (features->value != sizeof(XML_LChar))
7621 fail("Incorrect size of XML_LChar");
7622 break;
7623 default:
7624 break;
7625 }
7626 features++;
7627 }
7628 }
7629 }
7630 END_TEST
7631
7632 /* Regression test for GitHub Issue #17: memory leak parsing attribute
7633 * values with mixed bound and unbound namespaces.
7634 */
START_TEST(test_misc_attribute_leak)7635 START_TEST(test_misc_attribute_leak) {
7636 const char *text = "<D xmlns:L=\"D\" l:a='' L:a=''/>";
7637 XML_Memory_Handling_Suite memsuite
7638 = {tracking_malloc, tracking_realloc, tracking_free};
7639
7640 g_parser = XML_ParserCreate_MM(XCS("UTF-8"), &memsuite, XCS("\n"));
7641 expect_failure(text, XML_ERROR_UNBOUND_PREFIX, "Unbound prefixes not found");
7642 XML_ParserFree(g_parser);
7643 /* Prevent the teardown trying to double free */
7644 g_parser = NULL;
7645
7646 if (! tracking_report())
7647 fail("Memory leak found");
7648 }
7649 END_TEST
7650
7651 /* Test parser created for UTF-16LE is successful */
START_TEST(test_misc_utf16le)7652 START_TEST(test_misc_utf16le) {
7653 const char text[] =
7654 /* <?xml version='1.0'?><q>Hi</q> */
7655 "<\0?\0x\0m\0l\0 \0"
7656 "v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0?\0>\0"
7657 "<\0q\0>\0H\0i\0<\0/\0q\0>\0";
7658 const XML_Char *expected = XCS("Hi");
7659 CharData storage;
7660
7661 g_parser = XML_ParserCreate(XCS("UTF-16LE"));
7662 if (g_parser == NULL)
7663 fail("Parser not created");
7664
7665 CharData_Init(&storage);
7666 XML_SetUserData(g_parser, &storage);
7667 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
7668 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
7669 == XML_STATUS_ERROR)
7670 xml_failure(g_parser);
7671 CharData_CheckXMLChars(&storage, expected);
7672 }
7673 END_TEST
7674
7675 typedef struct {
7676 XML_Parser parser;
7677 int deep;
7678 } DataIssue240;
7679
7680 static void
start_element_issue_240(void * userData,const XML_Char * name,const XML_Char ** atts)7681 start_element_issue_240(void *userData, const XML_Char *name,
7682 const XML_Char **atts) {
7683 DataIssue240 *mydata = (DataIssue240 *)userData;
7684 UNUSED_P(name);
7685 UNUSED_P(atts);
7686 mydata->deep++;
7687 }
7688
7689 static void
end_element_issue_240(void * userData,const XML_Char * name)7690 end_element_issue_240(void *userData, const XML_Char *name) {
7691 DataIssue240 *mydata = (DataIssue240 *)userData;
7692
7693 UNUSED_P(name);
7694 mydata->deep--;
7695 if (mydata->deep == 0) {
7696 XML_StopParser(mydata->parser, 0);
7697 }
7698 }
7699
START_TEST(test_misc_stop_during_end_handler_issue_240_1)7700 START_TEST(test_misc_stop_during_end_handler_issue_240_1) {
7701 XML_Parser parser;
7702 DataIssue240 *mydata;
7703 enum XML_Status result;
7704 const char *const doc1 = "<doc><e1/><e><foo/></e></doc>";
7705
7706 parser = XML_ParserCreate(NULL);
7707 XML_SetElementHandler(parser, start_element_issue_240, end_element_issue_240);
7708 mydata = (DataIssue240 *)malloc(sizeof(DataIssue240));
7709 mydata->parser = parser;
7710 mydata->deep = 0;
7711 XML_SetUserData(parser, mydata);
7712
7713 result = XML_Parse(parser, doc1, (int)strlen(doc1), 1);
7714 XML_ParserFree(parser);
7715 free(mydata);
7716 if (result != XML_STATUS_ERROR)
7717 fail("Stopping the parser did not work as expected");
7718 }
7719 END_TEST
7720
START_TEST(test_misc_stop_during_end_handler_issue_240_2)7721 START_TEST(test_misc_stop_during_end_handler_issue_240_2) {
7722 XML_Parser parser;
7723 DataIssue240 *mydata;
7724 enum XML_Status result;
7725 const char *const doc2 = "<doc><elem/></doc>";
7726
7727 parser = XML_ParserCreate(NULL);
7728 XML_SetElementHandler(parser, start_element_issue_240, end_element_issue_240);
7729 mydata = (DataIssue240 *)malloc(sizeof(DataIssue240));
7730 mydata->parser = parser;
7731 mydata->deep = 0;
7732 XML_SetUserData(parser, mydata);
7733
7734 result = XML_Parse(parser, doc2, (int)strlen(doc2), 1);
7735 XML_ParserFree(parser);
7736 free(mydata);
7737 if (result != XML_STATUS_ERROR)
7738 fail("Stopping the parser did not work as expected");
7739 }
7740 END_TEST
7741
START_TEST(test_misc_deny_internal_entity_closing_doctype_issue_317)7742 START_TEST(test_misc_deny_internal_entity_closing_doctype_issue_317) {
7743 const char *const inputOne = "<!DOCTYPE d [\n"
7744 "<!ENTITY % e ']><d/>'>\n"
7745 "\n"
7746 "%e;";
7747 const char *const inputTwo = "<!DOCTYPE d [\n"
7748 "<!ENTITY % e1 ']><d/>'><!ENTITY % e2 '&e1;'>\n"
7749 "\n"
7750 "%e2;";
7751 const char *const inputThree = "<!DOCTYPE d [\n"
7752 "<!ENTITY % e ']><d'>\n"
7753 "\n"
7754 "%e;";
7755 const char *const inputIssue317 = "<!DOCTYPE doc [\n"
7756 "<!ENTITY % foo ']>\n"
7757 "<doc>Hell<oc (#PCDATA)*>'>\n"
7758 "%foo;\n"
7759 "]>\n"
7760 "<doc>Hello, world</dVc>";
7761
7762 const char *const inputs[] = {inputOne, inputTwo, inputThree, inputIssue317};
7763 size_t inputIndex = 0;
7764
7765 for (; inputIndex < sizeof(inputs) / sizeof(inputs[0]); inputIndex++) {
7766 XML_Parser parser;
7767 enum XML_Status parseResult;
7768 int setParamEntityResult;
7769 XML_Size lineNumber;
7770 XML_Size columnNumber;
7771 const char *const input = inputs[inputIndex];
7772
7773 parser = XML_ParserCreate(NULL);
7774 setParamEntityResult
7775 = XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
7776 if (setParamEntityResult != 1)
7777 fail("Failed to set XML_PARAM_ENTITY_PARSING_ALWAYS.");
7778
7779 parseResult = XML_Parse(parser, input, (int)strlen(input), 0);
7780 if (parseResult != XML_STATUS_ERROR) {
7781 parseResult = XML_Parse(parser, "", 0, 1);
7782 if (parseResult != XML_STATUS_ERROR) {
7783 fail("Parsing was expected to fail but succeeded.");
7784 }
7785 }
7786
7787 if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN)
7788 fail("Error code does not match XML_ERROR_INVALID_TOKEN");
7789
7790 lineNumber = XML_GetCurrentLineNumber(parser);
7791 if (lineNumber != 4)
7792 fail("XML_GetCurrentLineNumber does not work as expected.");
7793
7794 columnNumber = XML_GetCurrentColumnNumber(parser);
7795 if (columnNumber != 0)
7796 fail("XML_GetCurrentColumnNumber does not work as expected.");
7797
7798 XML_ParserFree(parser);
7799 }
7800 }
7801 END_TEST
7802
7803 static void
alloc_setup(void)7804 alloc_setup(void) {
7805 XML_Memory_Handling_Suite memsuite = {duff_allocator, duff_reallocator, free};
7806
7807 /* Ensure the parser creation will go through */
7808 allocation_count = ALLOC_ALWAYS_SUCCEED;
7809 reallocation_count = REALLOC_ALWAYS_SUCCEED;
7810 g_parser = XML_ParserCreate_MM(NULL, &memsuite, NULL);
7811 if (g_parser == NULL)
7812 fail("Parser not created");
7813 }
7814
7815 static void
alloc_teardown(void)7816 alloc_teardown(void) {
7817 basic_teardown();
7818 }
7819
7820 /* Test the effects of allocation failures on xml declaration processing */
START_TEST(test_alloc_parse_xdecl)7821 START_TEST(test_alloc_parse_xdecl) {
7822 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
7823 "<doc>Hello, world</doc>";
7824 int i;
7825 const int max_alloc_count = 15;
7826
7827 for (i = 0; i < max_alloc_count; i++) {
7828 allocation_count = i;
7829 XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler);
7830 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7831 != XML_STATUS_ERROR)
7832 break;
7833 /* Resetting the parser is insufficient, because some memory
7834 * allocations are cached within the parser. Instead we use
7835 * the teardown and setup routines to ensure that we have the
7836 * right sort of parser back in our hands.
7837 */
7838 alloc_teardown();
7839 alloc_setup();
7840 }
7841 if (i == 0)
7842 fail("Parse succeeded despite failing allocator");
7843 if (i == max_alloc_count)
7844 fail("Parse failed with max allocations");
7845 }
7846 END_TEST
7847
7848 /* As above, but with an encoding big enough to cause storing the
7849 * version information to expand the string pool being used.
7850 */
7851 static int XMLCALL
long_encoding_handler(void * userData,const XML_Char * encoding,XML_Encoding * info)7852 long_encoding_handler(void *userData, const XML_Char *encoding,
7853 XML_Encoding *info) {
7854 int i;
7855
7856 UNUSED_P(userData);
7857 UNUSED_P(encoding);
7858 for (i = 0; i < 256; i++)
7859 info->map[i] = i;
7860 info->data = NULL;
7861 info->convert = NULL;
7862 info->release = NULL;
7863 return XML_STATUS_OK;
7864 }
7865
START_TEST(test_alloc_parse_xdecl_2)7866 START_TEST(test_alloc_parse_xdecl_2) {
7867 const char *text
7868 = "<?xml version='1.0' encoding='"
7869 /* Each line is 64 characters */
7870 "ThisIsAStupidlyLongEncodingNameIntendedToTriggerPoolGrowth123456"
7871 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7872 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7873 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7874 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7875 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7876 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7877 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7878 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7879 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7880 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7881 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7882 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7883 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7884 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7885 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN"
7886 "'?>"
7887 "<doc>Hello, world</doc>";
7888 int i;
7889 const int max_alloc_count = 20;
7890
7891 for (i = 0; i < max_alloc_count; i++) {
7892 allocation_count = i;
7893 XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler);
7894 XML_SetUnknownEncodingHandler(g_parser, long_encoding_handler, NULL);
7895 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7896 != XML_STATUS_ERROR)
7897 break;
7898 /* See comment in test_alloc_parse_xdecl() */
7899 alloc_teardown();
7900 alloc_setup();
7901 }
7902 if (i == 0)
7903 fail("Parse succeeded despite failing allocator");
7904 if (i == max_alloc_count)
7905 fail("Parse failed with max allocations");
7906 }
7907 END_TEST
7908
7909 /* Test the effects of allocation failures on a straightforward parse */
START_TEST(test_alloc_parse_pi)7910 START_TEST(test_alloc_parse_pi) {
7911 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
7912 "<?pi unknown?>\n"
7913 "<doc>"
7914 "Hello, world"
7915 "</doc>";
7916 int i;
7917 const int max_alloc_count = 15;
7918
7919 for (i = 0; i < max_alloc_count; i++) {
7920 allocation_count = i;
7921 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
7922 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7923 != XML_STATUS_ERROR)
7924 break;
7925 /* See comment in test_alloc_parse_xdecl() */
7926 alloc_teardown();
7927 alloc_setup();
7928 }
7929 if (i == 0)
7930 fail("Parse succeeded despite failing allocator");
7931 if (i == max_alloc_count)
7932 fail("Parse failed with max allocations");
7933 }
7934 END_TEST
7935
START_TEST(test_alloc_parse_pi_2)7936 START_TEST(test_alloc_parse_pi_2) {
7937 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
7938 "<doc>"
7939 "Hello, world"
7940 "<?pi unknown?>\n"
7941 "</doc>";
7942 int i;
7943 const int max_alloc_count = 15;
7944
7945 for (i = 0; i < max_alloc_count; i++) {
7946 allocation_count = i;
7947 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
7948 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7949 != XML_STATUS_ERROR)
7950 break;
7951 /* See comment in test_alloc_parse_xdecl() */
7952 alloc_teardown();
7953 alloc_setup();
7954 }
7955 if (i == 0)
7956 fail("Parse succeeded despite failing allocator");
7957 if (i == max_alloc_count)
7958 fail("Parse failed with max allocations");
7959 }
7960 END_TEST
7961
START_TEST(test_alloc_parse_pi_3)7962 START_TEST(test_alloc_parse_pi_3) {
7963 const char *text
7964 = "<?"
7965 /* 64 characters per line */
7966 "This processing instruction should be long enough to ensure that"
7967 "it triggers the growth of an internal string pool when the "
7968 "allocator fails at a cruicial moment FGHIJKLMNOPABCDEFGHIJKLMNOP"
7969 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7970 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7971 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7972 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7973 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7974 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7975 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7976 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7977 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7978 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7979 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7980 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7981 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7982 "Q?><doc/>";
7983 int i;
7984 const int max_alloc_count = 20;
7985
7986 for (i = 0; i < max_alloc_count; i++) {
7987 allocation_count = i;
7988 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
7989 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7990 != XML_STATUS_ERROR)
7991 break;
7992 /* See comment in test_alloc_parse_xdecl() */
7993 alloc_teardown();
7994 alloc_setup();
7995 }
7996 if (i == 0)
7997 fail("Parse succeeded despite failing allocator");
7998 if (i == max_alloc_count)
7999 fail("Parse failed with max allocations");
8000 }
8001 END_TEST
8002
START_TEST(test_alloc_parse_comment)8003 START_TEST(test_alloc_parse_comment) {
8004 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
8005 "<!-- Test parsing this comment -->"
8006 "<doc>Hi</doc>";
8007 int i;
8008 const int max_alloc_count = 15;
8009
8010 for (i = 0; i < max_alloc_count; i++) {
8011 allocation_count = i;
8012 XML_SetCommentHandler(g_parser, dummy_comment_handler);
8013 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8014 != XML_STATUS_ERROR)
8015 break;
8016 /* See comment in test_alloc_parse_xdecl() */
8017 alloc_teardown();
8018 alloc_setup();
8019 }
8020 if (i == 0)
8021 fail("Parse succeeded despite failing allocator");
8022 if (i == max_alloc_count)
8023 fail("Parse failed with max allocations");
8024 }
8025 END_TEST
8026
START_TEST(test_alloc_parse_comment_2)8027 START_TEST(test_alloc_parse_comment_2) {
8028 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
8029 "<doc>"
8030 "Hello, world"
8031 "<!-- Parse this comment too -->"
8032 "</doc>";
8033 int i;
8034 const int max_alloc_count = 15;
8035
8036 for (i = 0; i < max_alloc_count; i++) {
8037 allocation_count = i;
8038 XML_SetCommentHandler(g_parser, dummy_comment_handler);
8039 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8040 != XML_STATUS_ERROR)
8041 break;
8042 /* See comment in test_alloc_parse_xdecl() */
8043 alloc_teardown();
8044 alloc_setup();
8045 }
8046 if (i == 0)
8047 fail("Parse succeeded despite failing allocator");
8048 if (i == max_alloc_count)
8049 fail("Parse failed with max allocations");
8050 }
8051 END_TEST
8052
8053 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)8054 external_entity_duff_loader(XML_Parser parser, const XML_Char *context,
8055 const XML_Char *base, const XML_Char *systemId,
8056 const XML_Char *publicId) {
8057 XML_Parser new_parser;
8058 unsigned int i;
8059 const unsigned int max_alloc_count = 10;
8060
8061 UNUSED_P(base);
8062 UNUSED_P(systemId);
8063 UNUSED_P(publicId);
8064 /* Try a few different allocation levels */
8065 for (i = 0; i < max_alloc_count; i++) {
8066 allocation_count = i;
8067 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8068 if (new_parser != NULL) {
8069 XML_ParserFree(new_parser);
8070 break;
8071 }
8072 }
8073 if (i == 0)
8074 fail("External parser creation ignored failing allocator");
8075 else if (i == max_alloc_count)
8076 fail("Extern parser not created with max allocation count");
8077
8078 /* Make sure other random allocation doesn't now fail */
8079 allocation_count = ALLOC_ALWAYS_SUCCEED;
8080
8081 /* Make sure the failure code path is executed too */
8082 return XML_STATUS_ERROR;
8083 }
8084
8085 /* Test that external parser creation running out of memory is
8086 * correctly reported. Based on the external entity test cases.
8087 */
START_TEST(test_alloc_create_external_parser)8088 START_TEST(test_alloc_create_external_parser) {
8089 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
8090 "<!DOCTYPE doc SYSTEM 'foo'>\n"
8091 "<doc>&entity;</doc>";
8092 char foo_text[] = "<!ELEMENT doc (#PCDATA)*>";
8093
8094 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8095 XML_SetUserData(g_parser, foo_text);
8096 XML_SetExternalEntityRefHandler(g_parser, external_entity_duff_loader);
8097 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8098 != XML_STATUS_ERROR) {
8099 fail("External parser allocator returned success incorrectly");
8100 }
8101 }
8102 END_TEST
8103
8104 /* More external parser memory allocation testing */
START_TEST(test_alloc_run_external_parser)8105 START_TEST(test_alloc_run_external_parser) {
8106 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
8107 "<!DOCTYPE doc SYSTEM 'foo'>\n"
8108 "<doc>&entity;</doc>";
8109 char foo_text[] = "<!ELEMENT doc (#PCDATA)*>";
8110 unsigned int i;
8111 const unsigned int max_alloc_count = 15;
8112
8113 for (i = 0; i < max_alloc_count; i++) {
8114 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8115 XML_SetUserData(g_parser, foo_text);
8116 XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader);
8117 allocation_count = i;
8118 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8119 != XML_STATUS_ERROR)
8120 break;
8121 /* See comment in test_alloc_parse_xdecl() */
8122 alloc_teardown();
8123 alloc_setup();
8124 }
8125 if (i == 0)
8126 fail("Parsing ignored failing allocator");
8127 else if (i == max_alloc_count)
8128 fail("Parsing failed with allocation count 10");
8129 }
8130 END_TEST
8131
8132 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)8133 external_entity_dbl_handler(XML_Parser parser, const XML_Char *context,
8134 const XML_Char *base, const XML_Char *systemId,
8135 const XML_Char *publicId) {
8136 intptr_t callno = (intptr_t)XML_GetUserData(parser);
8137 const char *text;
8138 XML_Parser new_parser;
8139 int i;
8140 const int max_alloc_count = 20;
8141
8142 UNUSED_P(base);
8143 UNUSED_P(systemId);
8144 UNUSED_P(publicId);
8145 if (callno == 0) {
8146 /* First time through, check how many calls to malloc occur */
8147 text = ("<!ELEMENT doc (e+)>\n"
8148 "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
8149 "<!ELEMENT e EMPTY>\n");
8150 allocation_count = 10000;
8151 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8152 if (new_parser == NULL) {
8153 fail("Unable to allocate first external parser");
8154 return XML_STATUS_ERROR;
8155 }
8156 /* Stash the number of calls in the user data */
8157 XML_SetUserData(parser, (void *)(intptr_t)(10000 - allocation_count));
8158 } else {
8159 text = ("<?xml version='1.0' encoding='us-ascii'?>"
8160 "<e/>");
8161 /* Try at varying levels to exercise more code paths */
8162 for (i = 0; i < max_alloc_count; i++) {
8163 allocation_count = callno + i;
8164 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8165 if (new_parser != NULL)
8166 break;
8167 }
8168 if (i == 0) {
8169 fail("Second external parser unexpectedly created");
8170 XML_ParserFree(new_parser);
8171 return XML_STATUS_ERROR;
8172 } else if (i == max_alloc_count) {
8173 fail("Second external parser not created");
8174 return XML_STATUS_ERROR;
8175 }
8176 }
8177
8178 allocation_count = ALLOC_ALWAYS_SUCCEED;
8179 if (_XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE)
8180 == XML_STATUS_ERROR) {
8181 xml_failure(new_parser);
8182 return XML_STATUS_ERROR;
8183 }
8184 XML_ParserFree(new_parser);
8185 return XML_STATUS_OK;
8186 }
8187
8188 /* Test that running out of memory in dtdCopy is correctly reported.
8189 * Based on test_default_ns_from_ext_subset_and_ext_ge()
8190 */
START_TEST(test_alloc_dtd_copy_default_atts)8191 START_TEST(test_alloc_dtd_copy_default_atts) {
8192 const char *text = "<?xml version='1.0'?>\n"
8193 "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n"
8194 " <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n"
8195 "]>\n"
8196 "<doc xmlns='http://example.org/ns1'>\n"
8197 "&en;\n"
8198 "</doc>";
8199
8200 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8201 XML_SetExternalEntityRefHandler(g_parser, external_entity_dbl_handler);
8202 XML_SetUserData(g_parser, NULL);
8203 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8204 == XML_STATUS_ERROR)
8205 xml_failure(g_parser);
8206 }
8207 END_TEST
8208
8209 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)8210 external_entity_dbl_handler_2(XML_Parser parser, const XML_Char *context,
8211 const XML_Char *base, const XML_Char *systemId,
8212 const XML_Char *publicId) {
8213 intptr_t callno = (intptr_t)XML_GetUserData(parser);
8214 const char *text;
8215 XML_Parser new_parser;
8216 enum XML_Status rv;
8217
8218 UNUSED_P(base);
8219 UNUSED_P(systemId);
8220 UNUSED_P(publicId);
8221 if (callno == 0) {
8222 /* Try different allocation levels for whole exercise */
8223 text = ("<!ELEMENT doc (e+)>\n"
8224 "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
8225 "<!ELEMENT e EMPTY>\n");
8226 XML_SetUserData(parser, (void *)(intptr_t)1);
8227 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8228 if (new_parser == NULL)
8229 return XML_STATUS_ERROR;
8230 rv = _XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE);
8231 } else {
8232 /* Just run through once */
8233 text = ("<?xml version='1.0' encoding='us-ascii'?>"
8234 "<e/>");
8235 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8236 if (new_parser == NULL)
8237 return XML_STATUS_ERROR;
8238 rv = _XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE);
8239 }
8240 XML_ParserFree(new_parser);
8241 if (rv == XML_STATUS_ERROR)
8242 return XML_STATUS_ERROR;
8243 return XML_STATUS_OK;
8244 }
8245
8246 /* Test more external entity allocation failure paths */
START_TEST(test_alloc_external_entity)8247 START_TEST(test_alloc_external_entity) {
8248 const char *text = "<?xml version='1.0'?>\n"
8249 "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n"
8250 " <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n"
8251 "]>\n"
8252 "<doc xmlns='http://example.org/ns1'>\n"
8253 "&en;\n"
8254 "</doc>";
8255 int i;
8256 const int alloc_test_max_repeats = 50;
8257
8258 for (i = 0; i < alloc_test_max_repeats; i++) {
8259 allocation_count = -1;
8260 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8261 XML_SetExternalEntityRefHandler(g_parser, external_entity_dbl_handler_2);
8262 XML_SetUserData(g_parser, NULL);
8263 allocation_count = i;
8264 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8265 == XML_STATUS_OK)
8266 break;
8267 /* See comment in test_alloc_parse_xdecl() */
8268 alloc_teardown();
8269 alloc_setup();
8270 }
8271 allocation_count = -1;
8272 if (i == 0)
8273 fail("External entity parsed despite duff allocator");
8274 if (i == alloc_test_max_repeats)
8275 fail("External entity not parsed at max allocation count");
8276 }
8277 END_TEST
8278
8279 /* Test more allocation failure paths */
8280 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)8281 external_entity_alloc_set_encoding(XML_Parser parser, const XML_Char *context,
8282 const XML_Char *base,
8283 const XML_Char *systemId,
8284 const XML_Char *publicId) {
8285 /* As for external_entity_loader() */
8286 const char *text = "<?xml encoding='iso-8859-3'?>"
8287 "\xC3\xA9";
8288 XML_Parser ext_parser;
8289 enum XML_Status status;
8290
8291 UNUSED_P(base);
8292 UNUSED_P(systemId);
8293 UNUSED_P(publicId);
8294 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8295 if (ext_parser == NULL)
8296 return XML_STATUS_ERROR;
8297 if (! XML_SetEncoding(ext_parser, XCS("utf-8"))) {
8298 XML_ParserFree(ext_parser);
8299 return XML_STATUS_ERROR;
8300 }
8301 status
8302 = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
8303 XML_ParserFree(ext_parser);
8304 if (status == XML_STATUS_ERROR)
8305 return XML_STATUS_ERROR;
8306 return XML_STATUS_OK;
8307 }
8308
START_TEST(test_alloc_ext_entity_set_encoding)8309 START_TEST(test_alloc_ext_entity_set_encoding) {
8310 const char *text = "<!DOCTYPE doc [\n"
8311 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
8312 "]>\n"
8313 "<doc>&en;</doc>";
8314 int i;
8315 const int max_allocation_count = 30;
8316
8317 for (i = 0; i < max_allocation_count; i++) {
8318 XML_SetExternalEntityRefHandler(g_parser,
8319 external_entity_alloc_set_encoding);
8320 allocation_count = i;
8321 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8322 == XML_STATUS_OK)
8323 break;
8324 allocation_count = -1;
8325 /* See comment in test_alloc_parse_xdecl() */
8326 alloc_teardown();
8327 alloc_setup();
8328 }
8329 if (i == 0)
8330 fail("Encoding check succeeded despite failing allocator");
8331 if (i == max_allocation_count)
8332 fail("Encoding failed at max allocation count");
8333 }
8334 END_TEST
8335
8336 static int XMLCALL
unknown_released_encoding_handler(void * data,const XML_Char * encoding,XML_Encoding * info)8337 unknown_released_encoding_handler(void *data, const XML_Char *encoding,
8338 XML_Encoding *info) {
8339 UNUSED_P(data);
8340 if (! xcstrcmp(encoding, XCS("unsupported-encoding"))) {
8341 int i;
8342
8343 for (i = 0; i < 256; i++)
8344 info->map[i] = i;
8345 info->data = NULL;
8346 info->convert = NULL;
8347 info->release = dummy_release;
8348 return XML_STATUS_OK;
8349 }
8350 return XML_STATUS_ERROR;
8351 }
8352
8353 /* Test the effects of allocation failure in internal entities.
8354 * Based on test_unknown_encoding_internal_entity
8355 */
START_TEST(test_alloc_internal_entity)8356 START_TEST(test_alloc_internal_entity) {
8357 const char *text = "<?xml version='1.0' encoding='unsupported-encoding'?>\n"
8358 "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n"
8359 "<test a='&foo;'/>";
8360 unsigned int i;
8361 const unsigned int max_alloc_count = 20;
8362
8363 for (i = 0; i < max_alloc_count; i++) {
8364 allocation_count = i;
8365 XML_SetUnknownEncodingHandler(g_parser, unknown_released_encoding_handler,
8366 NULL);
8367 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8368 != XML_STATUS_ERROR)
8369 break;
8370 /* See comment in test_alloc_parse_xdecl() */
8371 alloc_teardown();
8372 alloc_setup();
8373 }
8374 if (i == 0)
8375 fail("Internal entity worked despite failing allocations");
8376 else if (i == max_alloc_count)
8377 fail("Internal entity failed at max allocation count");
8378 }
8379 END_TEST
8380
8381 /* Test the robustness against allocation failure of element handling
8382 * Based on test_dtd_default_handling().
8383 */
START_TEST(test_alloc_dtd_default_handling)8384 START_TEST(test_alloc_dtd_default_handling) {
8385 const char *text = "<!DOCTYPE doc [\n"
8386 "<!ENTITY e SYSTEM 'http://example.org/e'>\n"
8387 "<!NOTATION n SYSTEM 'http://example.org/n'>\n"
8388 "<!ENTITY e1 SYSTEM 'http://example.org/e' NDATA n>\n"
8389 "<!ELEMENT doc (#PCDATA)>\n"
8390 "<!ATTLIST doc a CDATA #IMPLIED>\n"
8391 "<?pi in dtd?>\n"
8392 "<!--comment in dtd-->\n"
8393 "]>\n"
8394 "<doc><![CDATA[text in doc]]></doc>";
8395 const XML_Char *expected = XCS("\n\n\n\n\n\n\n\n\n<doc>text in doc</doc>");
8396 CharData storage;
8397 int i;
8398 const int max_alloc_count = 25;
8399
8400 for (i = 0; i < max_alloc_count; i++) {
8401 allocation_count = i;
8402 dummy_handler_flags = 0;
8403 XML_SetDefaultHandler(g_parser, accumulate_characters);
8404 XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_handler,
8405 dummy_end_doctype_handler);
8406 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
8407 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
8408 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
8409 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
8410 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
8411 XML_SetCommentHandler(g_parser, dummy_comment_handler);
8412 XML_SetCdataSectionHandler(g_parser, dummy_start_cdata_handler,
8413 dummy_end_cdata_handler);
8414 XML_SetUnparsedEntityDeclHandler(g_parser,
8415 dummy_unparsed_entity_decl_handler);
8416 CharData_Init(&storage);
8417 XML_SetUserData(g_parser, &storage);
8418 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
8419 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8420 != XML_STATUS_ERROR)
8421 break;
8422 /* See comment in test_alloc_parse_xdecl() */
8423 alloc_teardown();
8424 alloc_setup();
8425 }
8426 if (i == 0)
8427 fail("Default DTD parsed despite allocation failures");
8428 if (i == max_alloc_count)
8429 fail("Default DTD not parsed with maximum alloc count");
8430 CharData_CheckXMLChars(&storage, expected);
8431 if (dummy_handler_flags
8432 != (DUMMY_START_DOCTYPE_HANDLER_FLAG | DUMMY_END_DOCTYPE_HANDLER_FLAG
8433 | DUMMY_ENTITY_DECL_HANDLER_FLAG | DUMMY_NOTATION_DECL_HANDLER_FLAG
8434 | DUMMY_ELEMENT_DECL_HANDLER_FLAG | DUMMY_ATTLIST_DECL_HANDLER_FLAG
8435 | DUMMY_COMMENT_HANDLER_FLAG | DUMMY_PI_HANDLER_FLAG
8436 | DUMMY_START_CDATA_HANDLER_FLAG | DUMMY_END_CDATA_HANDLER_FLAG
8437 | DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG))
8438 fail("Not all handlers were called");
8439 }
8440 END_TEST
8441
8442 /* Test robustness of XML_SetEncoding() with a failing allocator */
START_TEST(test_alloc_explicit_encoding)8443 START_TEST(test_alloc_explicit_encoding) {
8444 int i;
8445 const int max_alloc_count = 5;
8446
8447 for (i = 0; i < max_alloc_count; i++) {
8448 allocation_count = i;
8449 if (XML_SetEncoding(g_parser, XCS("us-ascii")) == XML_STATUS_OK)
8450 break;
8451 }
8452 if (i == 0)
8453 fail("Encoding set despite failing allocator");
8454 else if (i == max_alloc_count)
8455 fail("Encoding not set at max allocation count");
8456 }
8457 END_TEST
8458
8459 /* Test robustness of XML_SetBase against a failing allocator */
START_TEST(test_alloc_set_base)8460 START_TEST(test_alloc_set_base) {
8461 const XML_Char *new_base = XCS("/local/file/name.xml");
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_SetBase(g_parser, new_base) == XML_STATUS_OK)
8468 break;
8469 }
8470 if (i == 0)
8471 fail("Base set despite failing allocator");
8472 else if (i == max_alloc_count)
8473 fail("Base not set with max allocation count");
8474 }
8475 END_TEST
8476
8477 /* Test buffer extension in the face of a duff reallocator */
START_TEST(test_alloc_realloc_buffer)8478 START_TEST(test_alloc_realloc_buffer) {
8479 const char *text = get_buffer_test_text;
8480 void *buffer;
8481 int i;
8482 const int max_realloc_count = 10;
8483
8484 /* Get a smallish buffer */
8485 for (i = 0; i < max_realloc_count; i++) {
8486 reallocation_count = i;
8487 buffer = XML_GetBuffer(g_parser, 1536);
8488 if (buffer == NULL)
8489 fail("1.5K buffer reallocation failed");
8490 assert(buffer != NULL);
8491 memcpy(buffer, text, strlen(text));
8492 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE)
8493 == XML_STATUS_OK)
8494 break;
8495 /* See comment in test_alloc_parse_xdecl() */
8496 alloc_teardown();
8497 alloc_setup();
8498 }
8499 reallocation_count = -1;
8500 if (i == 0)
8501 fail("Parse succeeded with no reallocation");
8502 else if (i == max_realloc_count)
8503 fail("Parse failed with max reallocation count");
8504 }
8505 END_TEST
8506
8507 /* Same test for external entity parsers */
8508 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)8509 external_entity_reallocator(XML_Parser parser, const XML_Char *context,
8510 const XML_Char *base, const XML_Char *systemId,
8511 const XML_Char *publicId) {
8512 const char *text = get_buffer_test_text;
8513 XML_Parser ext_parser;
8514 void *buffer;
8515 enum XML_Status status;
8516
8517 UNUSED_P(base);
8518 UNUSED_P(systemId);
8519 UNUSED_P(publicId);
8520 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8521 if (ext_parser == NULL)
8522 fail("Could not create external entity parser");
8523
8524 reallocation_count = (intptr_t)XML_GetUserData(parser);
8525 buffer = XML_GetBuffer(ext_parser, 1536);
8526 if (buffer == NULL)
8527 fail("Buffer allocation failed");
8528 assert(buffer != NULL);
8529 memcpy(buffer, text, strlen(text));
8530 status = XML_ParseBuffer(ext_parser, (int)strlen(text), XML_FALSE);
8531 reallocation_count = -1;
8532 XML_ParserFree(ext_parser);
8533 return (status == XML_STATUS_OK) ? XML_STATUS_OK : XML_STATUS_ERROR;
8534 }
8535
START_TEST(test_alloc_ext_entity_realloc_buffer)8536 START_TEST(test_alloc_ext_entity_realloc_buffer) {
8537 const char *text = "<!DOCTYPE doc [\n"
8538 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
8539 "]>\n"
8540 "<doc>&en;</doc>";
8541 int i;
8542 const int max_realloc_count = 10;
8543
8544 for (i = 0; i < max_realloc_count; i++) {
8545 XML_SetExternalEntityRefHandler(g_parser, external_entity_reallocator);
8546 XML_SetUserData(g_parser, (void *)(intptr_t)i);
8547 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8548 == XML_STATUS_OK)
8549 break;
8550 /* See comment in test_alloc_parse_xdecl() */
8551 alloc_teardown();
8552 alloc_setup();
8553 }
8554 if (i == 0)
8555 fail("Succeeded with no reallocations");
8556 if (i == max_realloc_count)
8557 fail("Failed with max reallocations");
8558 }
8559 END_TEST
8560
8561 /* Test elements with many attributes are handled correctly */
START_TEST(test_alloc_realloc_many_attributes)8562 START_TEST(test_alloc_realloc_many_attributes) {
8563 const char *text = "<!DOCTYPE doc [\n"
8564 "<!ATTLIST doc za CDATA 'default'>\n"
8565 "<!ATTLIST doc zb CDATA 'def2'>\n"
8566 "<!ATTLIST doc zc CDATA 'def3'>\n"
8567 "]>\n"
8568 "<doc a='1'"
8569 " b='2'"
8570 " c='3'"
8571 " d='4'"
8572 " e='5'"
8573 " f='6'"
8574 " g='7'"
8575 " h='8'"
8576 " i='9'"
8577 " j='10'"
8578 " k='11'"
8579 " l='12'"
8580 " m='13'"
8581 " n='14'"
8582 " p='15'"
8583 " q='16'"
8584 " r='17'"
8585 " s='18'>"
8586 "</doc>";
8587 int i;
8588 const int max_realloc_count = 10;
8589
8590 for (i = 0; i < max_realloc_count; i++) {
8591 reallocation_count = i;
8592 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8593 != XML_STATUS_ERROR)
8594 break;
8595 /* See comment in test_alloc_parse_xdecl() */
8596 alloc_teardown();
8597 alloc_setup();
8598 }
8599 if (i == 0)
8600 fail("Parse succeeded despite no reallocations");
8601 if (i == max_realloc_count)
8602 fail("Parse failed at max reallocations");
8603 }
8604 END_TEST
8605
8606 /* Test handling of a public entity with failing allocator */
START_TEST(test_alloc_public_entity_value)8607 START_TEST(test_alloc_public_entity_value) {
8608 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
8609 "<doc></doc>\n";
8610 char dtd_text[]
8611 = "<!ELEMENT doc EMPTY>\n"
8612 "<!ENTITY % e1 PUBLIC 'foo' 'bar.ent'>\n"
8613 "<!ENTITY % "
8614 /* Each line is 64 characters */
8615 "ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345"
8616 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8617 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8618 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8619 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8620 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8621 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8622 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8623 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8624 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8625 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8626 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8627 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8628 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8629 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8630 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8631 " '%e1;'>\n"
8632 "%e1;\n";
8633 int i;
8634 const int max_alloc_count = 50;
8635
8636 for (i = 0; i < max_alloc_count; i++) {
8637 allocation_count = i;
8638 dummy_handler_flags = 0;
8639 XML_SetUserData(g_parser, dtd_text);
8640 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8641 XML_SetExternalEntityRefHandler(g_parser, external_entity_public);
8642 /* Provoke a particular code path */
8643 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
8644 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8645 != XML_STATUS_ERROR)
8646 break;
8647 /* See comment in test_alloc_parse_xdecl() */
8648 alloc_teardown();
8649 alloc_setup();
8650 }
8651 if (i == 0)
8652 fail("Parsing worked despite failing allocation");
8653 if (i == max_alloc_count)
8654 fail("Parsing failed at max allocation count");
8655 if (dummy_handler_flags != DUMMY_ENTITY_DECL_HANDLER_FLAG)
8656 fail("Entity declaration handler not called");
8657 }
8658 END_TEST
8659
START_TEST(test_alloc_realloc_subst_public_entity_value)8660 START_TEST(test_alloc_realloc_subst_public_entity_value) {
8661 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
8662 "<doc></doc>\n";
8663 char dtd_text[]
8664 = "<!ELEMENT doc EMPTY>\n"
8665 "<!ENTITY % "
8666 /* Each line is 64 characters */
8667 "ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345"
8668 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8669 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8670 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8671 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8672 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8673 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8674 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8675 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8676 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8677 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8678 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8679 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8680 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8681 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8682 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8683 " PUBLIC 'foo' 'bar.ent'>\n"
8684 "%ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345"
8685 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
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 int i;
8701 const int max_realloc_count = 10;
8702
8703 for (i = 0; i < max_realloc_count; i++) {
8704 reallocation_count = i;
8705 XML_SetUserData(g_parser, dtd_text);
8706 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8707 XML_SetExternalEntityRefHandler(g_parser, external_entity_public);
8708 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8709 != XML_STATUS_ERROR)
8710 break;
8711 /* See comment in test_alloc_parse_xdecl() */
8712 alloc_teardown();
8713 alloc_setup();
8714 }
8715 if (i == 0)
8716 fail("Parsing worked despite failing reallocation");
8717 if (i == max_realloc_count)
8718 fail("Parsing failed at max reallocation count");
8719 }
8720 END_TEST
8721
START_TEST(test_alloc_parse_public_doctype)8722 START_TEST(test_alloc_parse_public_doctype) {
8723 const char *text
8724 = "<?xml version='1.0' encoding='utf-8'?>\n"
8725 "<!DOCTYPE doc PUBLIC '"
8726 /* 64 characters per line */
8727 "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/"
8728 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8729 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8730 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8731 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8732 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8733 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8734 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8735 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8736 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8737 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8738 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8739 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8740 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8741 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8742 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8743 "' 'test'>\n"
8744 "<doc></doc>";
8745 int i;
8746 const int max_alloc_count = 25;
8747
8748 for (i = 0; i < max_alloc_count; i++) {
8749 allocation_count = i;
8750 dummy_handler_flags = 0;
8751 XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_decl_handler,
8752 dummy_end_doctype_decl_handler);
8753 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8754 != XML_STATUS_ERROR)
8755 break;
8756 /* See comment in test_alloc_parse_xdecl() */
8757 alloc_teardown();
8758 alloc_setup();
8759 }
8760 if (i == 0)
8761 fail("Parse succeeded despite failing allocator");
8762 if (i == max_alloc_count)
8763 fail("Parse failed at maximum allocation count");
8764 if (dummy_handler_flags
8765 != (DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG
8766 | DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG))
8767 fail("Doctype handler functions not called");
8768 }
8769 END_TEST
8770
START_TEST(test_alloc_parse_public_doctype_long_name)8771 START_TEST(test_alloc_parse_public_doctype_long_name) {
8772 const char *text
8773 = "<?xml version='1.0' encoding='utf-8'?>\n"
8774 "<!DOCTYPE doc PUBLIC 'http://example.com/foo' '"
8775 /* 64 characters per line */
8776 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8777 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8778 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8779 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8780 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8781 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8782 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8783 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8784 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8785 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8786 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8787 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8788 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8789 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8790 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8791 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8792 "'>\n"
8793 "<doc></doc>";
8794 int i;
8795 const int max_alloc_count = 25;
8796
8797 for (i = 0; i < max_alloc_count; i++) {
8798 allocation_count = i;
8799 XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_decl_handler,
8800 dummy_end_doctype_decl_handler);
8801 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8802 != XML_STATUS_ERROR)
8803 break;
8804 /* See comment in test_alloc_parse_xdecl() */
8805 alloc_teardown();
8806 alloc_setup();
8807 }
8808 if (i == 0)
8809 fail("Parse succeeded despite failing allocator");
8810 if (i == max_alloc_count)
8811 fail("Parse failed at maximum allocation count");
8812 }
8813 END_TEST
8814
8815 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)8816 external_entity_alloc(XML_Parser parser, const XML_Char *context,
8817 const XML_Char *base, const XML_Char *systemId,
8818 const XML_Char *publicId) {
8819 const char *text = (const char *)XML_GetUserData(parser);
8820 XML_Parser ext_parser;
8821 int parse_res;
8822
8823 UNUSED_P(base);
8824 UNUSED_P(systemId);
8825 UNUSED_P(publicId);
8826 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8827 if (ext_parser == NULL)
8828 return XML_STATUS_ERROR;
8829 parse_res
8830 = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
8831 XML_ParserFree(ext_parser);
8832 return parse_res;
8833 }
8834
8835 /* Test foreign DTD handling */
START_TEST(test_alloc_set_foreign_dtd)8836 START_TEST(test_alloc_set_foreign_dtd) {
8837 const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n"
8838 "<doc>&entity;</doc>";
8839 char text2[] = "<!ELEMENT doc (#PCDATA)*>";
8840 int i;
8841 const int max_alloc_count = 25;
8842
8843 for (i = 0; i < max_alloc_count; i++) {
8844 allocation_count = i;
8845 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8846 XML_SetUserData(g_parser, &text2);
8847 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
8848 if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE)
8849 fail("Could not set foreign DTD");
8850 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_TRUE)
8851 != XML_STATUS_ERROR)
8852 break;
8853 /* See comment in test_alloc_parse_xdecl() */
8854 alloc_teardown();
8855 alloc_setup();
8856 }
8857 if (i == 0)
8858 fail("Parse succeeded despite failing allocator");
8859 if (i == max_alloc_count)
8860 fail("Parse failed at maximum allocation count");
8861 }
8862 END_TEST
8863
8864 /* Test based on ibm/valid/P32/ibm32v04.xml */
START_TEST(test_alloc_attribute_enum_value)8865 START_TEST(test_alloc_attribute_enum_value) {
8866 const char *text = "<?xml version='1.0' standalone='no'?>\n"
8867 "<!DOCTYPE animal SYSTEM 'test.dtd'>\n"
8868 "<animal>This is a \n <a/> \n\nyellow tiger</animal>";
8869 char dtd_text[] = "<!ELEMENT animal (#PCDATA|a)*>\n"
8870 "<!ELEMENT a EMPTY>\n"
8871 "<!ATTLIST animal xml:space (default|preserve) 'preserve'>";
8872 int i;
8873 const int max_alloc_count = 30;
8874
8875 for (i = 0; i < max_alloc_count; i++) {
8876 allocation_count = i;
8877 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
8878 XML_SetUserData(g_parser, dtd_text);
8879 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8880 /* An attribute list handler provokes a different code path */
8881 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
8882 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8883 != XML_STATUS_ERROR)
8884 break;
8885 /* See comment in test_alloc_parse_xdecl() */
8886 alloc_teardown();
8887 alloc_setup();
8888 }
8889 if (i == 0)
8890 fail("Parse succeeded despite failing allocator");
8891 if (i == max_alloc_count)
8892 fail("Parse failed at maximum allocation count");
8893 }
8894 END_TEST
8895
8896 /* Test attribute enums sufficient to overflow the string pool */
START_TEST(test_alloc_realloc_attribute_enum_value)8897 START_TEST(test_alloc_realloc_attribute_enum_value) {
8898 const char *text = "<?xml version='1.0' standalone='no'?>\n"
8899 "<!DOCTYPE animal SYSTEM 'test.dtd'>\n"
8900 "<animal>This is a yellow tiger</animal>";
8901 /* We wish to define a collection of attribute enums that will
8902 * cause the string pool storing them to have to expand. This
8903 * means more than 1024 bytes, including the parentheses and
8904 * separator bars.
8905 */
8906 char dtd_text[]
8907 = "<!ELEMENT animal (#PCDATA)*>\n"
8908 "<!ATTLIST animal thing "
8909 "(default"
8910 /* Each line is 64 characters */
8911 "|ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8912 "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8913 "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8914 "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8915 "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8916 "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8917 "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8918 "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8919 "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8920 "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8921 "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8922 "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8923 "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8924 "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8925 "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8926 "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO)"
8927 " 'default'>";
8928 int i;
8929 const int max_realloc_count = 10;
8930
8931 for (i = 0; i < max_realloc_count; i++) {
8932 reallocation_count = i;
8933 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
8934 XML_SetUserData(g_parser, dtd_text);
8935 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8936 /* An attribute list handler provokes a different code path */
8937 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
8938 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8939 != XML_STATUS_ERROR)
8940 break;
8941 /* See comment in test_alloc_parse_xdecl() */
8942 alloc_teardown();
8943 alloc_setup();
8944 }
8945 if (i == 0)
8946 fail("Parse succeeded despite failing reallocator");
8947 if (i == max_realloc_count)
8948 fail("Parse failed at maximum reallocation count");
8949 }
8950 END_TEST
8951
8952 /* Test attribute enums in a #IMPLIED attribute forcing pool growth */
START_TEST(test_alloc_realloc_implied_attribute)8953 START_TEST(test_alloc_realloc_implied_attribute) {
8954 /* Forcing this particular code path is a balancing act. The
8955 * addition of the closing parenthesis and terminal NUL must be
8956 * what pushes the string of enums over the 1024-byte limit,
8957 * otherwise a different code path will pick up the realloc.
8958 */
8959 const char *text
8960 = "<!DOCTYPE doc [\n"
8961 "<!ELEMENT doc EMPTY>\n"
8962 "<!ATTLIST doc a "
8963 /* Each line is 64 characters */
8964 "(ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8965 "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8966 "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8967 "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8968 "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8969 "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8970 "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8971 "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8972 "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8973 "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8974 "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8975 "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8976 "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8977 "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8978 "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8979 "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN)"
8980 " #IMPLIED>\n"
8981 "]><doc/>";
8982 int i;
8983 const int max_realloc_count = 10;
8984
8985 for (i = 0; i < max_realloc_count; i++) {
8986 reallocation_count = i;
8987 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
8988 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8989 != XML_STATUS_ERROR)
8990 break;
8991 /* See comment in test_alloc_parse_xdecl() */
8992 alloc_teardown();
8993 alloc_setup();
8994 }
8995 if (i == 0)
8996 fail("Parse succeeded despite failing reallocator");
8997 if (i == max_realloc_count)
8998 fail("Parse failed at maximum reallocation count");
8999 }
9000 END_TEST
9001
9002 /* Test attribute enums in a defaulted attribute forcing pool growth */
START_TEST(test_alloc_realloc_default_attribute)9003 START_TEST(test_alloc_realloc_default_attribute) {
9004 /* Forcing this particular code path is a balancing act. The
9005 * addition of the closing parenthesis and terminal NUL must be
9006 * what pushes the string of enums over the 1024-byte limit,
9007 * otherwise a different code path will pick up the realloc.
9008 */
9009 const char *text
9010 = "<!DOCTYPE doc [\n"
9011 "<!ELEMENT doc EMPTY>\n"
9012 "<!ATTLIST doc a "
9013 /* Each line is 64 characters */
9014 "(ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9015 "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9016 "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9017 "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9018 "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9019 "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9020 "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9021 "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9022 "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9023 "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9024 "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9025 "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9026 "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9027 "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9028 "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9029 "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN)"
9030 " 'ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO'"
9031 ">\n]><doc/>";
9032 int i;
9033 const int max_realloc_count = 10;
9034
9035 for (i = 0; i < max_realloc_count; i++) {
9036 reallocation_count = i;
9037 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
9038 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9039 != XML_STATUS_ERROR)
9040 break;
9041 /* See comment in test_alloc_parse_xdecl() */
9042 alloc_teardown();
9043 alloc_setup();
9044 }
9045 if (i == 0)
9046 fail("Parse succeeded despite failing reallocator");
9047 if (i == max_realloc_count)
9048 fail("Parse failed at maximum reallocation count");
9049 }
9050 END_TEST
9051
9052 /* Test long notation name with dodgy allocator */
START_TEST(test_alloc_notation)9053 START_TEST(test_alloc_notation) {
9054 const char *text
9055 = "<!DOCTYPE doc [\n"
9056 "<!NOTATION "
9057 /* Each line is 64 characters */
9058 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9059 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9060 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9061 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9062 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9063 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9064 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9065 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9066 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9067 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9068 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9069 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9070 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9071 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9072 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9073 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9074 " SYSTEM 'http://example.org/n'>\n"
9075 "<!ENTITY e SYSTEM 'http://example.org/e' NDATA "
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 ">\n"
9093 "<!ELEMENT doc EMPTY>\n"
9094 "]>\n<doc/>";
9095 int i;
9096 const int max_alloc_count = 20;
9097
9098 for (i = 0; i < max_alloc_count; i++) {
9099 allocation_count = i;
9100 dummy_handler_flags = 0;
9101 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
9102 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
9103 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9104 != XML_STATUS_ERROR)
9105 break;
9106 /* See comment in test_alloc_parse_xdecl() */
9107 alloc_teardown();
9108 alloc_setup();
9109 }
9110 if (i == 0)
9111 fail("Parse succeeded despite allocation failures");
9112 if (i == max_alloc_count)
9113 fail("Parse failed at maximum allocation count");
9114 if (dummy_handler_flags
9115 != (DUMMY_ENTITY_DECL_HANDLER_FLAG | DUMMY_NOTATION_DECL_HANDLER_FLAG))
9116 fail("Entity declaration handler not called");
9117 }
9118 END_TEST
9119
9120 /* Test public notation with dodgy allocator */
START_TEST(test_alloc_public_notation)9121 START_TEST(test_alloc_public_notation) {
9122 const char *text
9123 = "<!DOCTYPE doc [\n"
9124 "<!NOTATION note PUBLIC '"
9125 /* 64 characters per line */
9126 "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/"
9127 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9128 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9129 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9130 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9131 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9132 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9133 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9134 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9135 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9136 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9137 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9138 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9139 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9140 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9141 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9142 "' 'foo'>\n"
9143 "<!ENTITY e SYSTEM 'http://example.com/e' NDATA note>\n"
9144 "<!ELEMENT doc EMPTY>\n"
9145 "]>\n<doc/>";
9146 int i;
9147 const int max_alloc_count = 20;
9148
9149 for (i = 0; i < max_alloc_count; i++) {
9150 allocation_count = i;
9151 dummy_handler_flags = 0;
9152 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
9153 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9154 != XML_STATUS_ERROR)
9155 break;
9156 /* See comment in test_alloc_parse_xdecl() */
9157 alloc_teardown();
9158 alloc_setup();
9159 }
9160 if (i == 0)
9161 fail("Parse succeeded despite allocation failures");
9162 if (i == max_alloc_count)
9163 fail("Parse failed at maximum allocation count");
9164 if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG)
9165 fail("Notation handler not called");
9166 }
9167 END_TEST
9168
9169 /* Test public notation with dodgy allocator */
START_TEST(test_alloc_system_notation)9170 START_TEST(test_alloc_system_notation) {
9171 const char *text
9172 = "<!DOCTYPE doc [\n"
9173 "<!NOTATION note SYSTEM '"
9174 /* 64 characters per line */
9175 "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/"
9176 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9177 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9178 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9179 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9180 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9181 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9182 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9183 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9184 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9185 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9186 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9187 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9188 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9189 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9190 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9191 "'>\n"
9192 "<!ENTITY e SYSTEM 'http://example.com/e' NDATA note>\n"
9193 "<!ELEMENT doc EMPTY>\n"
9194 "]>\n<doc/>";
9195 int i;
9196 const int max_alloc_count = 20;
9197
9198 for (i = 0; i < max_alloc_count; i++) {
9199 allocation_count = i;
9200 dummy_handler_flags = 0;
9201 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
9202 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9203 != XML_STATUS_ERROR)
9204 break;
9205 /* See comment in test_alloc_parse_xdecl() */
9206 alloc_teardown();
9207 alloc_setup();
9208 }
9209 if (i == 0)
9210 fail("Parse succeeded despite allocation failures");
9211 if (i == max_alloc_count)
9212 fail("Parse failed at maximum allocation count");
9213 if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG)
9214 fail("Notation handler not called");
9215 }
9216 END_TEST
9217
START_TEST(test_alloc_nested_groups)9218 START_TEST(test_alloc_nested_groups) {
9219 const char *text
9220 = "<!DOCTYPE doc [\n"
9221 "<!ELEMENT doc "
9222 /* Sixteen elements per line */
9223 "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,"
9224 "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?"
9225 "))))))))))))))))))))))))))))))))>\n"
9226 "<!ELEMENT e EMPTY>"
9227 "]>\n"
9228 "<doc><e/></doc>";
9229 CharData storage;
9230 int i;
9231 const int max_alloc_count = 20;
9232
9233 for (i = 0; i < max_alloc_count; i++) {
9234 allocation_count = i;
9235 CharData_Init(&storage);
9236 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
9237 XML_SetStartElementHandler(g_parser, record_element_start_handler);
9238 XML_SetUserData(g_parser, &storage);
9239 dummy_handler_flags = 0;
9240 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9241 != XML_STATUS_ERROR)
9242 break;
9243 /* See comment in test_alloc_parse_xdecl() */
9244 alloc_teardown();
9245 alloc_setup();
9246 }
9247
9248 if (i == 0)
9249 fail("Parse succeeded despite failing reallocator");
9250 if (i == max_alloc_count)
9251 fail("Parse failed at maximum reallocation count");
9252 CharData_CheckXMLChars(&storage, XCS("doce"));
9253 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9254 fail("Element handler not fired");
9255 }
9256 END_TEST
9257
START_TEST(test_alloc_realloc_nested_groups)9258 START_TEST(test_alloc_realloc_nested_groups) {
9259 const char *text
9260 = "<!DOCTYPE doc [\n"
9261 "<!ELEMENT doc "
9262 /* Sixteen elements per line */
9263 "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,"
9264 "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?"
9265 "))))))))))))))))))))))))))))))))>\n"
9266 "<!ELEMENT e EMPTY>"
9267 "]>\n"
9268 "<doc><e/></doc>";
9269 CharData storage;
9270 int i;
9271 const int max_realloc_count = 10;
9272
9273 for (i = 0; i < max_realloc_count; i++) {
9274 reallocation_count = i;
9275 CharData_Init(&storage);
9276 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
9277 XML_SetStartElementHandler(g_parser, record_element_start_handler);
9278 XML_SetUserData(g_parser, &storage);
9279 dummy_handler_flags = 0;
9280 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9281 != XML_STATUS_ERROR)
9282 break;
9283 /* See comment in test_alloc_parse_xdecl() */
9284 alloc_teardown();
9285 alloc_setup();
9286 }
9287
9288 if (i == 0)
9289 fail("Parse succeeded despite failing reallocator");
9290 if (i == max_realloc_count)
9291 fail("Parse failed at maximum reallocation count");
9292 CharData_CheckXMLChars(&storage, XCS("doce"));
9293 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9294 fail("Element handler not fired");
9295 }
9296 END_TEST
9297
START_TEST(test_alloc_large_group)9298 START_TEST(test_alloc_large_group) {
9299 const char *text = "<!DOCTYPE doc [\n"
9300 "<!ELEMENT doc ("
9301 "a1|a2|a3|a4|a5|a6|a7|a8|"
9302 "b1|b2|b3|b4|b5|b6|b7|b8|"
9303 "c1|c2|c3|c4|c5|c6|c7|c8|"
9304 "d1|d2|d3|d4|d5|d6|d7|d8|"
9305 "e1"
9306 ")+>\n"
9307 "]>\n"
9308 "<doc>\n"
9309 "<a1/>\n"
9310 "</doc>\n";
9311 int i;
9312 const int max_alloc_count = 50;
9313
9314 for (i = 0; i < max_alloc_count; i++) {
9315 allocation_count = i;
9316 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
9317 dummy_handler_flags = 0;
9318 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9319 != XML_STATUS_ERROR)
9320 break;
9321 /* See comment in test_alloc_parse_xdecl() */
9322 alloc_teardown();
9323 alloc_setup();
9324 }
9325 if (i == 0)
9326 fail("Parse succeeded despite failing allocator");
9327 if (i == max_alloc_count)
9328 fail("Parse failed at maximum allocation count");
9329 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9330 fail("Element handler flag not raised");
9331 }
9332 END_TEST
9333
START_TEST(test_alloc_realloc_group_choice)9334 START_TEST(test_alloc_realloc_group_choice) {
9335 const char *text = "<!DOCTYPE doc [\n"
9336 "<!ELEMENT doc ("
9337 "a1|a2|a3|a4|a5|a6|a7|a8|"
9338 "b1|b2|b3|b4|b5|b6|b7|b8|"
9339 "c1|c2|c3|c4|c5|c6|c7|c8|"
9340 "d1|d2|d3|d4|d5|d6|d7|d8|"
9341 "e1"
9342 ")+>\n"
9343 "]>\n"
9344 "<doc>\n"
9345 "<a1/>\n"
9346 "<b2 attr='foo'>This is a foo</b2>\n"
9347 "<c3></c3>\n"
9348 "</doc>\n";
9349 int i;
9350 const int max_realloc_count = 10;
9351
9352 for (i = 0; i < max_realloc_count; i++) {
9353 reallocation_count = i;
9354 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
9355 dummy_handler_flags = 0;
9356 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9357 != XML_STATUS_ERROR)
9358 break;
9359 /* See comment in test_alloc_parse_xdecl() */
9360 alloc_teardown();
9361 alloc_setup();
9362 }
9363 if (i == 0)
9364 fail("Parse succeeded despite failing reallocator");
9365 if (i == max_realloc_count)
9366 fail("Parse failed at maximum reallocation count");
9367 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9368 fail("Element handler flag not raised");
9369 }
9370 END_TEST
9371
START_TEST(test_alloc_pi_in_epilog)9372 START_TEST(test_alloc_pi_in_epilog) {
9373 const char *text = "<doc></doc>\n"
9374 "<?pi in epilog?>";
9375 int i;
9376 const int max_alloc_count = 15;
9377
9378 for (i = 0; i < max_alloc_count; i++) {
9379 allocation_count = i;
9380 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
9381 dummy_handler_flags = 0;
9382 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9383 != XML_STATUS_ERROR)
9384 break;
9385 /* See comment in test_alloc_parse_xdecl() */
9386 alloc_teardown();
9387 alloc_setup();
9388 }
9389 if (i == 0)
9390 fail("Parse completed despite failing allocator");
9391 if (i == max_alloc_count)
9392 fail("Parse failed at maximum allocation count");
9393 if (dummy_handler_flags != DUMMY_PI_HANDLER_FLAG)
9394 fail("Processing instruction handler not invoked");
9395 }
9396 END_TEST
9397
START_TEST(test_alloc_comment_in_epilog)9398 START_TEST(test_alloc_comment_in_epilog) {
9399 const char *text = "<doc></doc>\n"
9400 "<!-- comment in epilog -->";
9401 int i;
9402 const int max_alloc_count = 15;
9403
9404 for (i = 0; i < max_alloc_count; i++) {
9405 allocation_count = i;
9406 XML_SetCommentHandler(g_parser, dummy_comment_handler);
9407 dummy_handler_flags = 0;
9408 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9409 != XML_STATUS_ERROR)
9410 break;
9411 /* See comment in test_alloc_parse_xdecl() */
9412 alloc_teardown();
9413 alloc_setup();
9414 }
9415 if (i == 0)
9416 fail("Parse completed despite failing allocator");
9417 if (i == max_alloc_count)
9418 fail("Parse failed at maximum allocation count");
9419 if (dummy_handler_flags != DUMMY_COMMENT_HANDLER_FLAG)
9420 fail("Processing instruction handler not invoked");
9421 }
9422 END_TEST
9423
START_TEST(test_alloc_realloc_long_attribute_value)9424 START_TEST(test_alloc_realloc_long_attribute_value) {
9425 const char *text
9426 = "<!DOCTYPE doc [<!ENTITY foo '"
9427 /* Each line is 64 characters */
9428 "This entity will be substituted as an attribute value, and is "
9429 "calculated to be exactly long enough that the terminating NUL "
9430 "that the library adds internally will trigger the string pool to"
9431 "grow. GHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9432 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9433 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9434 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9435 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9436 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9437 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9438 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9439 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9440 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9441 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9442 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9443 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9444 "'>]>\n"
9445 "<doc a='&foo;'></doc>";
9446 int i;
9447 const int max_realloc_count = 10;
9448
9449 for (i = 0; i < max_realloc_count; i++) {
9450 reallocation_count = i;
9451 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9452 != XML_STATUS_ERROR)
9453 break;
9454 /* See comment in test_alloc_parse_xdecl() */
9455 alloc_teardown();
9456 alloc_setup();
9457 }
9458 if (i == 0)
9459 fail("Parse succeeded despite failing reallocator");
9460 if (i == max_realloc_count)
9461 fail("Parse failed at maximum reallocation count");
9462 }
9463 END_TEST
9464
START_TEST(test_alloc_attribute_whitespace)9465 START_TEST(test_alloc_attribute_whitespace) {
9466 const char *text = "<doc a=' '></doc>";
9467 int i;
9468 const int max_alloc_count = 15;
9469
9470 for (i = 0; i < max_alloc_count; i++) {
9471 allocation_count = i;
9472 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9473 != XML_STATUS_ERROR)
9474 break;
9475 /* See comment in test_alloc_parse_xdecl() */
9476 alloc_teardown();
9477 alloc_setup();
9478 }
9479 if (i == 0)
9480 fail("Parse succeeded despite failing allocator");
9481 if (i == max_alloc_count)
9482 fail("Parse failed at maximum allocation count");
9483 }
9484 END_TEST
9485
START_TEST(test_alloc_attribute_predefined_entity)9486 START_TEST(test_alloc_attribute_predefined_entity) {
9487 const char *text = "<doc a='&'></doc>";
9488 int i;
9489 const int max_alloc_count = 15;
9490
9491 for (i = 0; i < max_alloc_count; i++) {
9492 allocation_count = i;
9493 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9494 != XML_STATUS_ERROR)
9495 break;
9496 /* See comment in test_alloc_parse_xdecl() */
9497 alloc_teardown();
9498 alloc_setup();
9499 }
9500 if (i == 0)
9501 fail("Parse succeeded despite failing allocator");
9502 if (i == max_alloc_count)
9503 fail("Parse failed at maximum allocation count");
9504 }
9505 END_TEST
9506
9507 /* Test that a character reference at the end of a suitably long
9508 * default value for an attribute can trigger pool growth, and recovers
9509 * if the allocator fails on it.
9510 */
START_TEST(test_alloc_long_attr_default_with_char_ref)9511 START_TEST(test_alloc_long_attr_default_with_char_ref) {
9512 const char *text
9513 = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '"
9514 /* 64 characters per line */
9515 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9516 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9517 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9518 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9519 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9520 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9521 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9522 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9523 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9524 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9525 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9526 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9527 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9528 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9529 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9530 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHI"
9531 "1'>]>\n"
9532 "<doc/>";
9533 int i;
9534 const int max_alloc_count = 20;
9535
9536 for (i = 0; i < max_alloc_count; i++) {
9537 allocation_count = i;
9538 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9539 != XML_STATUS_ERROR)
9540 break;
9541 /* See comment in test_alloc_parse_xdecl() */
9542 alloc_teardown();
9543 alloc_setup();
9544 }
9545 if (i == 0)
9546 fail("Parse succeeded despite failing allocator");
9547 if (i == max_alloc_count)
9548 fail("Parse failed at maximum allocation count");
9549 }
9550 END_TEST
9551
9552 /* Test that a long character reference substitution triggers a pool
9553 * expansion correctly for an attribute value.
9554 */
START_TEST(test_alloc_long_attr_value)9555 START_TEST(test_alloc_long_attr_value) {
9556 const char *text
9557 = "<!DOCTYPE test [<!ENTITY foo '\n"
9558 /* 64 characters per line */
9559 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9560 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9561 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9562 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9563 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9564 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9565 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9566 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9567 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9568 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9569 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9570 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9571 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9572 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9573 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9574 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9575 "'>]>\n"
9576 "<test a='&foo;'/>";
9577 int i;
9578 const int max_alloc_count = 25;
9579
9580 for (i = 0; i < max_alloc_count; i++) {
9581 allocation_count = i;
9582 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9583 != XML_STATUS_ERROR)
9584 break;
9585 /* See comment in test_alloc_parse_xdecl() */
9586 alloc_teardown();
9587 alloc_setup();
9588 }
9589 if (i == 0)
9590 fail("Parse succeeded despite failing allocator");
9591 if (i == max_alloc_count)
9592 fail("Parse failed at maximum allocation count");
9593 }
9594 END_TEST
9595
9596 /* Test that an error in a nested parameter entity substitution is
9597 * handled correctly. It seems unlikely that the code path being
9598 * exercised can be reached purely by carefully crafted XML, but an
9599 * allocation error in the right place will definitely do it.
9600 */
START_TEST(test_alloc_nested_entities)9601 START_TEST(test_alloc_nested_entities) {
9602 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n"
9603 "<doc />";
9604 ExtFaults test_data
9605 = {"<!ENTITY % pe1 '"
9606 /* 64 characters per line */
9607 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9608 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9609 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9610 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9611 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9612 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9613 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9614 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9615 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9616 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9617 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9618 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9619 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9620 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9621 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9622 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9623 "'>\n"
9624 "<!ENTITY % pe2 '%pe1;'>\n"
9625 "%pe2;",
9626 "Memory Fail not faulted", NULL, XML_ERROR_NO_MEMORY};
9627
9628 /* Causes an allocation error in a nested storeEntityValue() */
9629 allocation_count = 12;
9630 XML_SetUserData(g_parser, &test_data);
9631 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9632 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
9633 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
9634 "Entity allocation failure not noted");
9635 }
9636 END_TEST
9637
START_TEST(test_alloc_realloc_param_entity_newline)9638 START_TEST(test_alloc_realloc_param_entity_newline) {
9639 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
9640 "<doc/>";
9641 char dtd_text[]
9642 = "<!ENTITY % pe '<!ATTLIST doc att CDATA \""
9643 /* 64 characters per line */
9644 "This default value is carefully crafted so that the carriage "
9645 "return right at the end of the entity string causes an internal "
9646 "string pool to have to grow. This allows us to test the alloc "
9647 "failure path from that point. OPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9648 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9649 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9650 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9651 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9652 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9653 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9654 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9655 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9656 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9657 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9658 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9659 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDE"
9660 "\">\n'>"
9661 "%pe;\n";
9662 int i;
9663 const int max_realloc_count = 5;
9664
9665 for (i = 0; i < max_realloc_count; i++) {
9666 reallocation_count = i;
9667 XML_SetUserData(g_parser, dtd_text);
9668 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9669 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9670 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9671 != XML_STATUS_ERROR)
9672 break;
9673 /* See comment in test_alloc_parse_xdecl() */
9674 alloc_teardown();
9675 alloc_setup();
9676 }
9677 if (i == 0)
9678 fail("Parse succeeded despite failing reallocator");
9679 if (i == max_realloc_count)
9680 fail("Parse failed at maximum reallocation count");
9681 }
9682 END_TEST
9683
START_TEST(test_alloc_realloc_ce_extends_pe)9684 START_TEST(test_alloc_realloc_ce_extends_pe) {
9685 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
9686 "<doc/>";
9687 char dtd_text[]
9688 = "<!ENTITY % pe '<!ATTLIST doc att CDATA \""
9689 /* 64 characters per line */
9690 "This default value is carefully crafted so that the character "
9691 "entity at the end causes an internal string pool to have to "
9692 "grow. This allows us to test the allocation failure path from "
9693 "that point onwards. EFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9694 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9695 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9696 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9697 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9698 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9699 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9700 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9701 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9702 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9703 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9704 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9705 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGQ"
9706 "\">\n'>"
9707 "%pe;\n";
9708 int i;
9709 const int max_realloc_count = 5;
9710
9711 for (i = 0; i < max_realloc_count; i++) {
9712 reallocation_count = i;
9713 XML_SetUserData(g_parser, dtd_text);
9714 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9715 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9716 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9717 != XML_STATUS_ERROR)
9718 break;
9719 /* See comment in test_alloc_parse_xdecl() */
9720 alloc_teardown();
9721 alloc_setup();
9722 }
9723 if (i == 0)
9724 fail("Parse succeeded despite failing reallocator");
9725 if (i == max_realloc_count)
9726 fail("Parse failed at maximum reallocation count");
9727 }
9728 END_TEST
9729
START_TEST(test_alloc_realloc_attributes)9730 START_TEST(test_alloc_realloc_attributes) {
9731 const char *text = "<!DOCTYPE doc [\n"
9732 " <!ATTLIST doc\n"
9733 " a1 (a|b|c) 'a'\n"
9734 " a2 (foo|bar) #IMPLIED\n"
9735 " a3 NMTOKEN #IMPLIED\n"
9736 " a4 NMTOKENS #IMPLIED\n"
9737 " a5 ID #IMPLIED\n"
9738 " a6 IDREF #IMPLIED\n"
9739 " a7 IDREFS #IMPLIED\n"
9740 " a8 ENTITY #IMPLIED\n"
9741 " a9 ENTITIES #IMPLIED\n"
9742 " a10 CDATA #IMPLIED\n"
9743 " >]>\n"
9744 "<doc>wombat</doc>\n";
9745 int i;
9746 const int max_realloc_count = 5;
9747
9748 for (i = 0; i < max_realloc_count; i++) {
9749 reallocation_count = i;
9750 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9751 != XML_STATUS_ERROR)
9752 break;
9753 /* See comment in test_alloc_parse_xdecl() */
9754 alloc_teardown();
9755 alloc_setup();
9756 }
9757
9758 if (i == 0)
9759 fail("Parse succeeded despite failing reallocator");
9760 if (i == max_realloc_count)
9761 fail("Parse failed at maximum reallocation count");
9762 }
9763 END_TEST
9764
START_TEST(test_alloc_long_doc_name)9765 START_TEST(test_alloc_long_doc_name) {
9766 const char *text =
9767 /* 64 characters per line */
9768 "<LongRootElementNameThatWillCauseTheNextAllocationToExpandTheStr"
9769 "ingPoolForTheDTDQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9770 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9771 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9772 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9773 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9774 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9775 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9776 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9777 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9778 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9779 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9780 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9781 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9782 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9783 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9784 " a='1'/>";
9785 int i;
9786 const int max_alloc_count = 20;
9787
9788 for (i = 0; i < max_alloc_count; i++) {
9789 allocation_count = i;
9790 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9791 != XML_STATUS_ERROR)
9792 break;
9793 /* See comment in test_alloc_parse_xdecl() */
9794 alloc_teardown();
9795 alloc_setup();
9796 }
9797 if (i == 0)
9798 fail("Parsing worked despite failing reallocations");
9799 else if (i == max_alloc_count)
9800 fail("Parsing failed even at max reallocation count");
9801 }
9802 END_TEST
9803
START_TEST(test_alloc_long_base)9804 START_TEST(test_alloc_long_base) {
9805 const char *text = "<!DOCTYPE doc [\n"
9806 " <!ENTITY e SYSTEM 'foo'>\n"
9807 "]>\n"
9808 "<doc>&e;</doc>";
9809 char entity_text[] = "Hello world";
9810 const XML_Char *base =
9811 /* 64 characters per line */
9812 /* clang-format off */
9813 XCS("LongBaseURI/that/will/overflow/an/internal/buffer/and/cause/it/t")
9814 XCS("o/have/to/grow/PQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9815 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9816 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9817 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9818 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9819 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9820 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9821 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9822 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9823 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9824 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9825 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9826 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9827 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9828 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/");
9829 /* clang-format on */
9830 int i;
9831 const int max_alloc_count = 25;
9832
9833 for (i = 0; i < max_alloc_count; i++) {
9834 allocation_count = i;
9835 XML_SetUserData(g_parser, entity_text);
9836 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9837 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9838 if (XML_SetBase(g_parser, base) == XML_STATUS_ERROR) {
9839 XML_ParserReset(g_parser, NULL);
9840 continue;
9841 }
9842 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9843 != XML_STATUS_ERROR)
9844 break;
9845 /* See comment in test_alloc_parse_xdecl() */
9846 alloc_teardown();
9847 alloc_setup();
9848 }
9849 if (i == 0)
9850 fail("Parsing worked despite failing allocations");
9851 else if (i == max_alloc_count)
9852 fail("Parsing failed even at max allocation count");
9853 }
9854 END_TEST
9855
START_TEST(test_alloc_long_public_id)9856 START_TEST(test_alloc_long_public_id) {
9857 const char *text
9858 = "<!DOCTYPE doc [\n"
9859 " <!ENTITY e PUBLIC '"
9860 /* 64 characters per line */
9861 "LongPublicIDThatShouldResultInAnInternalStringPoolGrowingAtASpec"
9862 "ificMomentKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9863 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9864 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9865 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9866 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9867 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9868 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9869 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9870 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9871 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9872 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9873 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9874 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9875 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9876 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9877 "' 'bar'>\n"
9878 "]>\n"
9879 "<doc>&e;</doc>";
9880 char entity_text[] = "Hello world";
9881 int i;
9882 const int max_alloc_count = 40;
9883
9884 for (i = 0; i < max_alloc_count; i++) {
9885 allocation_count = i;
9886 XML_SetUserData(g_parser, entity_text);
9887 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9888 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9889 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9890 != XML_STATUS_ERROR)
9891 break;
9892 /* See comment in test_alloc_parse_xdecl() */
9893 alloc_teardown();
9894 alloc_setup();
9895 }
9896 if (i == 0)
9897 fail("Parsing worked despite failing allocations");
9898 else if (i == max_alloc_count)
9899 fail("Parsing failed even at max allocation count");
9900 }
9901 END_TEST
9902
START_TEST(test_alloc_long_entity_value)9903 START_TEST(test_alloc_long_entity_value) {
9904 const char *text
9905 = "<!DOCTYPE doc [\n"
9906 " <!ENTITY e1 '"
9907 /* 64 characters per line */
9908 "Long entity value that should provoke a string pool to grow whil"
9909 "e setting up to parse the external entity below. xyz0123456789AB"
9910 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9911 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9912 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9913 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9914 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9915 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9916 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9917 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9918 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9919 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9920 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9921 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9922 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9923 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9924 "'>\n"
9925 " <!ENTITY e2 SYSTEM 'bar'>\n"
9926 "]>\n"
9927 "<doc>&e2;</doc>";
9928 char entity_text[] = "Hello world";
9929 int i;
9930 const int max_alloc_count = 40;
9931
9932 for (i = 0; i < max_alloc_count; i++) {
9933 allocation_count = i;
9934 XML_SetUserData(g_parser, entity_text);
9935 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9936 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9937 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9938 != XML_STATUS_ERROR)
9939 break;
9940 /* See comment in test_alloc_parse_xdecl() */
9941 alloc_teardown();
9942 alloc_setup();
9943 }
9944 if (i == 0)
9945 fail("Parsing worked despite failing allocations");
9946 else if (i == max_alloc_count)
9947 fail("Parsing failed even at max allocation count");
9948 }
9949 END_TEST
9950
START_TEST(test_alloc_long_notation)9951 START_TEST(test_alloc_long_notation) {
9952 const char *text
9953 = "<!DOCTYPE doc [\n"
9954 " <!NOTATION note SYSTEM '"
9955 /* 64 characters per line */
9956 "ALongNotationNameThatShouldProvokeStringPoolGrowthWhileCallingAn"
9957 "ExternalEntityParserUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9958 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9959 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9960 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9961 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9962 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9963 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9964 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9965 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9966 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9967 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9968 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9969 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9970 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9971 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9972 "'>\n"
9973 " <!ENTITY e1 SYSTEM 'foo' NDATA "
9974 /* 64 characters per line */
9975 "ALongNotationNameThatShouldProvokeStringPoolGrowthWhileCallingAn"
9976 "ExternalEntityParserUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
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 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9991 ">\n"
9992 " <!ENTITY e2 SYSTEM 'bar'>\n"
9993 "]>\n"
9994 "<doc>&e2;</doc>";
9995 ExtOption options[]
9996 = {{XCS("foo"), "Entity Foo"}, {XCS("bar"), "Entity Bar"}, {NULL, NULL}};
9997 int i;
9998 const int max_alloc_count = 40;
9999
10000 for (i = 0; i < max_alloc_count; i++) {
10001 allocation_count = i;
10002 XML_SetUserData(g_parser, options);
10003 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
10004 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
10005 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10006 != XML_STATUS_ERROR)
10007 break;
10008
10009 /* See comment in test_alloc_parse_xdecl() */
10010 alloc_teardown();
10011 alloc_setup();
10012 }
10013 if (i == 0)
10014 fail("Parsing worked despite failing allocations");
10015 else if (i == max_alloc_count)
10016 fail("Parsing failed even at max allocation count");
10017 }
10018 END_TEST
10019
10020 static void
nsalloc_setup(void)10021 nsalloc_setup(void) {
10022 XML_Memory_Handling_Suite memsuite = {duff_allocator, duff_reallocator, free};
10023 XML_Char ns_sep[2] = {' ', '\0'};
10024
10025 /* Ensure the parser creation will go through */
10026 allocation_count = ALLOC_ALWAYS_SUCCEED;
10027 reallocation_count = REALLOC_ALWAYS_SUCCEED;
10028 g_parser = XML_ParserCreate_MM(NULL, &memsuite, ns_sep);
10029 if (g_parser == NULL)
10030 fail("Parser not created");
10031 }
10032
10033 static void
nsalloc_teardown(void)10034 nsalloc_teardown(void) {
10035 basic_teardown();
10036 }
10037
10038 /* Test the effects of allocation failure in simple namespace parsing.
10039 * Based on test_ns_default_with_empty_uri()
10040 */
START_TEST(test_nsalloc_xmlns)10041 START_TEST(test_nsalloc_xmlns) {
10042 const char *text = "<doc xmlns='http://example.org/'>\n"
10043 " <e xmlns=''/>\n"
10044 "</doc>";
10045 unsigned int i;
10046 const unsigned int max_alloc_count = 30;
10047
10048 for (i = 0; i < max_alloc_count; i++) {
10049 allocation_count = i;
10050 /* Exercise more code paths with a default handler */
10051 XML_SetDefaultHandler(g_parser, dummy_default_handler);
10052 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10053 != XML_STATUS_ERROR)
10054 break;
10055 /* Resetting the parser is insufficient, because some memory
10056 * allocations are cached within the parser. Instead we use
10057 * the teardown and setup routines to ensure that we have the
10058 * right sort of parser back in our hands.
10059 */
10060 nsalloc_teardown();
10061 nsalloc_setup();
10062 }
10063 if (i == 0)
10064 fail("Parsing worked despite failing allocations");
10065 else if (i == max_alloc_count)
10066 fail("Parsing failed even at maximum allocation count");
10067 }
10068 END_TEST
10069
10070 /* Test XML_ParseBuffer interface with namespace and a dicky allocator */
START_TEST(test_nsalloc_parse_buffer)10071 START_TEST(test_nsalloc_parse_buffer) {
10072 const char *text = "<doc>Hello</doc>";
10073 void *buffer;
10074
10075 /* Try a parse before the start of the world */
10076 /* (Exercises new code path) */
10077 if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_ERROR)
10078 fail("Pre-init XML_ParseBuffer not faulted");
10079 if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_BUFFER)
10080 fail("Pre-init XML_ParseBuffer faulted for wrong reason");
10081
10082 buffer = XML_GetBuffer(g_parser, 1 /* any small number greater than 0 */);
10083 if (buffer == NULL)
10084 fail("Could not acquire parse buffer");
10085
10086 allocation_count = 0;
10087 if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_ERROR)
10088 fail("Pre-init XML_ParseBuffer not faulted");
10089 if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_MEMORY)
10090 fail("Pre-init XML_ParseBuffer faulted for wrong reason");
10091
10092 /* Now with actual memory allocation */
10093 allocation_count = ALLOC_ALWAYS_SUCCEED;
10094 if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_OK)
10095 xml_failure(g_parser);
10096
10097 /* Check that resuming an unsuspended parser is faulted */
10098 if (XML_ResumeParser(g_parser) != XML_STATUS_ERROR)
10099 fail("Resuming unsuspended parser not faulted");
10100 if (XML_GetErrorCode(g_parser) != XML_ERROR_NOT_SUSPENDED)
10101 xml_failure(g_parser);
10102
10103 /* Get the parser into suspended state */
10104 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
10105 resumable = XML_TRUE;
10106 buffer = XML_GetBuffer(g_parser, (int)strlen(text));
10107 if (buffer == NULL)
10108 fail("Could not acquire parse buffer");
10109 assert(buffer != NULL);
10110 memcpy(buffer, text, strlen(text));
10111 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE)
10112 != XML_STATUS_SUSPENDED)
10113 xml_failure(g_parser);
10114 if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE)
10115 xml_failure(g_parser);
10116 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE)
10117 != XML_STATUS_ERROR)
10118 fail("Suspended XML_ParseBuffer not faulted");
10119 if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED)
10120 xml_failure(g_parser);
10121 if (XML_GetBuffer(g_parser, (int)strlen(text)) != NULL)
10122 fail("Suspended XML_GetBuffer not faulted");
10123
10124 /* Get it going again and complete the world */
10125 XML_SetCharacterDataHandler(g_parser, NULL);
10126 if (XML_ResumeParser(g_parser) != XML_STATUS_OK)
10127 xml_failure(g_parser);
10128 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE)
10129 != XML_STATUS_ERROR)
10130 fail("Post-finishing XML_ParseBuffer not faulted");
10131 if (XML_GetErrorCode(g_parser) != XML_ERROR_FINISHED)
10132 xml_failure(g_parser);
10133 if (XML_GetBuffer(g_parser, (int)strlen(text)) != NULL)
10134 fail("Post-finishing XML_GetBuffer not faulted");
10135 }
10136 END_TEST
10137
10138 /* Check handling of long prefix names (pool growth) */
START_TEST(test_nsalloc_long_prefix)10139 START_TEST(test_nsalloc_long_prefix) {
10140 const char *text
10141 = "<"
10142 /* 64 characters per line */
10143 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10144 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10145 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10146 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10147 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10148 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10149 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10150 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10151 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10152 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10153 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10154 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10155 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10156 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10157 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10158 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10159 ":foo xmlns:"
10160 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
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 "='http://example.org/'>"
10177 "</"
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 ":foo>";
10195 int i;
10196 const int max_alloc_count = 40;
10197
10198 for (i = 0; i < max_alloc_count; i++) {
10199 allocation_count = i;
10200 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10201 != XML_STATUS_ERROR)
10202 break;
10203 /* See comment in test_nsalloc_xmlns() */
10204 nsalloc_teardown();
10205 nsalloc_setup();
10206 }
10207 if (i == 0)
10208 fail("Parsing worked despite failing allocations");
10209 else if (i == max_alloc_count)
10210 fail("Parsing failed even at max allocation count");
10211 }
10212 END_TEST
10213
10214 /* Check handling of long uri names (pool growth) */
START_TEST(test_nsalloc_long_uri)10215 START_TEST(test_nsalloc_long_uri) {
10216 const char *text
10217 = "<foo:e xmlns:foo='http://example.org/"
10218 /* 64 characters per line */
10219 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10220 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10221 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10222 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10223 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10224 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10225 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10226 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10227 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10228 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10229 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10230 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10231 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10232 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10233 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10234 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10235 "' bar:a='12'\n"
10236 "xmlns:bar='http://example.org/"
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 "'>"
10254 "</foo:e>";
10255 int i;
10256 const int max_alloc_count = 40;
10257
10258 for (i = 0; i < max_alloc_count; i++) {
10259 allocation_count = i;
10260 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10261 != XML_STATUS_ERROR)
10262 break;
10263 /* See comment in test_nsalloc_xmlns() */
10264 nsalloc_teardown();
10265 nsalloc_setup();
10266 }
10267 if (i == 0)
10268 fail("Parsing worked despite failing allocations");
10269 else if (i == max_alloc_count)
10270 fail("Parsing failed even at max allocation count");
10271 }
10272 END_TEST
10273
10274 /* Test handling of long attribute names with prefixes */
START_TEST(test_nsalloc_long_attr)10275 START_TEST(test_nsalloc_long_attr) {
10276 const char *text
10277 = "<foo:e xmlns:foo='http://example.org/' bar:"
10278 /* 64 characters per line */
10279 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10280 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10281 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10282 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10283 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10284 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10285 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10286 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10287 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10288 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10289 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10290 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10291 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10292 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10293 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10294 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10295 "='12'\n"
10296 "xmlns:bar='http://example.org/'>"
10297 "</foo:e>";
10298 int i;
10299 const int max_alloc_count = 40;
10300
10301 for (i = 0; i < max_alloc_count; i++) {
10302 allocation_count = i;
10303 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10304 != XML_STATUS_ERROR)
10305 break;
10306 /* See comment in test_nsalloc_xmlns() */
10307 nsalloc_teardown();
10308 nsalloc_setup();
10309 }
10310 if (i == 0)
10311 fail("Parsing worked despite failing allocations");
10312 else if (i == max_alloc_count)
10313 fail("Parsing failed even at max allocation count");
10314 }
10315 END_TEST
10316
10317 /* Test handling of an attribute name with a long namespace prefix */
START_TEST(test_nsalloc_long_attr_prefix)10318 START_TEST(test_nsalloc_long_attr_prefix) {
10319 const char *text
10320 = "<foo:e xmlns:foo='http://example.org/' "
10321 /* 64 characters per line */
10322 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10323 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10324 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10325 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10326 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10327 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10328 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10329 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10330 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10331 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10332 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10333 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10334 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10335 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10336 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10337 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10338 ":a='12'\n"
10339 "xmlns:"
10340 /* 64 characters per line */
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 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10357 "='http://example.org/'>"
10358 "</foo:e>";
10359 const XML_Char *elemstr[] = {
10360 /* clang-format off */
10361 XCS("http://example.org/ e foo"),
10362 XCS("http://example.org/ a ")
10363 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10364 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10365 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10366 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10367 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10368 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10369 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10370 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10371 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10372 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10373 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10374 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10375 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10376 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10377 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10378 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10379 /* clang-format on */
10380 };
10381 int i;
10382 const int max_alloc_count = 40;
10383
10384 for (i = 0; i < max_alloc_count; i++) {
10385 allocation_count = i;
10386 XML_SetReturnNSTriplet(g_parser, XML_TRUE);
10387 XML_SetUserData(g_parser, (void *)elemstr);
10388 XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
10389 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10390 != XML_STATUS_ERROR)
10391 break;
10392 /* See comment in test_nsalloc_xmlns() */
10393 nsalloc_teardown();
10394 nsalloc_setup();
10395 }
10396 if (i == 0)
10397 fail("Parsing worked despite failing allocations");
10398 else if (i == max_alloc_count)
10399 fail("Parsing failed even at max allocation count");
10400 }
10401 END_TEST
10402
10403 /* Test attribute handling in the face of a dodgy reallocator */
START_TEST(test_nsalloc_realloc_attributes)10404 START_TEST(test_nsalloc_realloc_attributes) {
10405 const char *text = "<foo:e xmlns:foo='http://example.org/' bar:a='12'\n"
10406 " xmlns:bar='http://example.org/'>"
10407 "</foo:e>";
10408 int i;
10409 const int max_realloc_count = 10;
10410
10411 for (i = 0; i < max_realloc_count; i++) {
10412 reallocation_count = i;
10413 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10414 != XML_STATUS_ERROR)
10415 break;
10416 /* See comment in test_nsalloc_xmlns() */
10417 nsalloc_teardown();
10418 nsalloc_setup();
10419 }
10420 if (i == 0)
10421 fail("Parsing worked despite failing reallocations");
10422 else if (i == max_realloc_count)
10423 fail("Parsing failed at max reallocation count");
10424 }
10425 END_TEST
10426
10427 /* Test long element names with namespaces under a failing allocator */
START_TEST(test_nsalloc_long_element)10428 START_TEST(test_nsalloc_long_element) {
10429 const char *text
10430 = "<foo:thisisalongenoughelementnametotriggerareallocation\n"
10431 " xmlns:foo='http://example.org/' bar:a='12'\n"
10432 " xmlns:bar='http://example.org/'>"
10433 "</foo:thisisalongenoughelementnametotriggerareallocation>";
10434 const XML_Char *elemstr[]
10435 = {XCS("http://example.org/")
10436 XCS(" thisisalongenoughelementnametotriggerareallocation foo"),
10437 XCS("http://example.org/ a bar")};
10438 int i;
10439 const int max_alloc_count = 30;
10440
10441 for (i = 0; i < max_alloc_count; i++) {
10442 allocation_count = i;
10443 XML_SetReturnNSTriplet(g_parser, XML_TRUE);
10444 XML_SetUserData(g_parser, (void *)elemstr);
10445 XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
10446 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10447 != XML_STATUS_ERROR)
10448 break;
10449 /* See comment in test_nsalloc_xmlns() */
10450 nsalloc_teardown();
10451 nsalloc_setup();
10452 }
10453 if (i == 0)
10454 fail("Parsing worked despite failing reallocations");
10455 else if (i == max_alloc_count)
10456 fail("Parsing failed at max reallocation count");
10457 }
10458 END_TEST
10459
10460 /* Test the effects of reallocation failure when reassigning a
10461 * binding.
10462 *
10463 * XML_ParserReset does not free the BINDING structures used by a
10464 * parser, but instead adds them to an internal free list to be reused
10465 * as necessary. Likewise the URI buffers allocated for the binding
10466 * aren't freed, but kept attached to their existing binding. If the
10467 * new binding has a longer URI, it will need reallocation. This test
10468 * provokes that reallocation, and tests the control path if it fails.
10469 */
START_TEST(test_nsalloc_realloc_binding_uri)10470 START_TEST(test_nsalloc_realloc_binding_uri) {
10471 const char *first = "<doc xmlns='http://example.org/'>\n"
10472 " <e xmlns='' />\n"
10473 "</doc>";
10474 const char *second
10475 = "<doc xmlns='http://example.org/long/enough/URI/to/reallocate/'>\n"
10476 " <e xmlns='' />\n"
10477 "</doc>";
10478 unsigned i;
10479 const unsigned max_realloc_count = 10;
10480
10481 /* First, do a full parse that will leave bindings around */
10482 if (_XML_Parse_SINGLE_BYTES(g_parser, first, (int)strlen(first), XML_TRUE)
10483 == XML_STATUS_ERROR)
10484 xml_failure(g_parser);
10485
10486 /* Now repeat with a longer URI and a duff reallocator */
10487 for (i = 0; i < max_realloc_count; i++) {
10488 XML_ParserReset(g_parser, NULL);
10489 reallocation_count = i;
10490 if (_XML_Parse_SINGLE_BYTES(g_parser, second, (int)strlen(second), XML_TRUE)
10491 != XML_STATUS_ERROR)
10492 break;
10493 }
10494 if (i == 0)
10495 fail("Parsing worked despite failing reallocation");
10496 else if (i == max_realloc_count)
10497 fail("Parsing failed at max reallocation count");
10498 }
10499 END_TEST
10500
10501 /* Check handling of long prefix names (pool growth) */
START_TEST(test_nsalloc_realloc_long_prefix)10502 START_TEST(test_nsalloc_realloc_long_prefix) {
10503 const char *text
10504 = "<"
10505 /* 64 characters per line */
10506 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10507 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10508 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10509 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10510 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10511 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10512 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10513 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10514 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10515 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10516 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10517 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10518 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10519 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10520 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10521 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10522 ":foo xmlns:"
10523 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10524 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10525 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10526 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10527 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10528 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10529 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10530 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10531 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10532 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10533 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10534 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10535 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10536 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10537 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10538 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10539 "='http://example.org/'>"
10540 "</"
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 ":foo>";
10558 int i;
10559 const int max_realloc_count = 12;
10560
10561 for (i = 0; i < max_realloc_count; i++) {
10562 reallocation_count = i;
10563 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10564 != XML_STATUS_ERROR)
10565 break;
10566 /* See comment in test_nsalloc_xmlns() */
10567 nsalloc_teardown();
10568 nsalloc_setup();
10569 }
10570 if (i == 0)
10571 fail("Parsing worked despite failing reallocations");
10572 else if (i == max_realloc_count)
10573 fail("Parsing failed even at max reallocation count");
10574 }
10575 END_TEST
10576
10577 /* Check handling of even long prefix names (different code path) */
START_TEST(test_nsalloc_realloc_longer_prefix)10578 START_TEST(test_nsalloc_realloc_longer_prefix) {
10579 const char *text
10580 = "<"
10581 /* 64 characters per line */
10582 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10583 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10584 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10585 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10586 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10587 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10588 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10589 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10590 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10591 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10592 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10593 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10594 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10595 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10596 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10597 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10598 "Q:foo xmlns:"
10599 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
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 "Q='http://example.org/'>"
10616 "</"
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:foo>";
10634 int i;
10635 const int max_realloc_count = 12;
10636
10637 for (i = 0; i < max_realloc_count; i++) {
10638 reallocation_count = i;
10639 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10640 != XML_STATUS_ERROR)
10641 break;
10642 /* See comment in test_nsalloc_xmlns() */
10643 nsalloc_teardown();
10644 nsalloc_setup();
10645 }
10646 if (i == 0)
10647 fail("Parsing worked despite failing reallocations");
10648 else if (i == max_realloc_count)
10649 fail("Parsing failed even at max reallocation count");
10650 }
10651 END_TEST
10652
START_TEST(test_nsalloc_long_namespace)10653 START_TEST(test_nsalloc_long_namespace) {
10654 const char *text1
10655 = "<"
10656 /* 64 characters per line */
10657 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10658 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10659 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10660 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10661 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10662 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10663 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10664 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10665 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10666 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10667 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10668 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10669 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10670 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10671 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10672 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10673 ":e xmlns:"
10674 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
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 "='http://example.org/'>\n";
10691 const char *text2
10692 = "<"
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 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10709 ":f "
10710 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10711 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10712 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10713 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10714 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10715 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10716 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10717 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10718 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10719 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10720 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10721 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10722 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10723 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10724 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10725 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10726 ":attr='foo'/>\n"
10727 "</"
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 ":e>";
10745 int i;
10746 const int max_alloc_count = 40;
10747
10748 for (i = 0; i < max_alloc_count; i++) {
10749 allocation_count = i;
10750 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
10751 != XML_STATUS_ERROR
10752 && _XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2),
10753 XML_TRUE)
10754 != XML_STATUS_ERROR)
10755 break;
10756 /* See comment in test_nsalloc_xmlns() */
10757 nsalloc_teardown();
10758 nsalloc_setup();
10759 }
10760 if (i == 0)
10761 fail("Parsing worked despite failing allocations");
10762 else if (i == max_alloc_count)
10763 fail("Parsing failed even at max allocation count");
10764 }
10765 END_TEST
10766
10767 /* Using a slightly shorter namespace name provokes allocations in
10768 * slightly different places in the code.
10769 */
START_TEST(test_nsalloc_less_long_namespace)10770 START_TEST(test_nsalloc_less_long_namespace) {
10771 const char *text
10772 = "<"
10773 /* 64 characters per line */
10774 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10775 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10776 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10777 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10778 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10779 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10780 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10781 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10782 ":e xmlns:"
10783 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10784 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10785 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10786 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10787 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10788 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10789 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10790 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10791 "='http://example.org/'>\n"
10792 "<"
10793 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10794 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10795 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10796 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10797 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10798 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10799 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10800 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10801 ":f "
10802 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10803 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10804 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10805 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10806 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10807 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10808 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10809 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10810 ":att='foo'/>\n"
10811 "</"
10812 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10813 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10814 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10815 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10816 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10817 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10818 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10819 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10820 ":e>";
10821 int i;
10822 const int max_alloc_count = 40;
10823
10824 for (i = 0; i < max_alloc_count; i++) {
10825 allocation_count = i;
10826 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10827 != XML_STATUS_ERROR)
10828 break;
10829 /* See comment in test_nsalloc_xmlns() */
10830 nsalloc_teardown();
10831 nsalloc_setup();
10832 }
10833 if (i == 0)
10834 fail("Parsing worked despite failing allocations");
10835 else if (i == max_alloc_count)
10836 fail("Parsing failed even at max allocation count");
10837 }
10838 END_TEST
10839
START_TEST(test_nsalloc_long_context)10840 START_TEST(test_nsalloc_long_context) {
10841 const char *text
10842 = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10843 " <!ATTLIST doc baz ID #REQUIRED>\n"
10844 " <!ENTITY en SYSTEM 'bar'>\n"
10845 "]>\n"
10846 "<doc xmlns='http://example.org/"
10847 /* 64 characters per line */
10848 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10849 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10850 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10851 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10852 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10853 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10854 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10855 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10856 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10857 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10858 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10859 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10860 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10861 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10862 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10863 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKL"
10864 "' baz='2'>\n"
10865 "&en;"
10866 "</doc>";
10867 ExtOption options[] = {
10868 {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}};
10869 int i;
10870 const int max_alloc_count = 70;
10871
10872 for (i = 0; i < max_alloc_count; i++) {
10873 allocation_count = i;
10874 XML_SetUserData(g_parser, options);
10875 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
10876 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
10877 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10878 != XML_STATUS_ERROR)
10879 break;
10880
10881 /* See comment in test_nsalloc_xmlns() */
10882 nsalloc_teardown();
10883 nsalloc_setup();
10884 }
10885 if (i == 0)
10886 fail("Parsing worked despite failing allocations");
10887 else if (i == max_alloc_count)
10888 fail("Parsing failed even at max allocation count");
10889 }
10890 END_TEST
10891
10892 /* This function is void; it will throw a fail() on error, so if it
10893 * returns normally it must have succeeded.
10894 */
10895 static void
context_realloc_test(const char * text)10896 context_realloc_test(const char *text) {
10897 ExtOption options[] = {
10898 {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}};
10899 int i;
10900 const int max_realloc_count = 6;
10901
10902 for (i = 0; i < max_realloc_count; i++) {
10903 reallocation_count = i;
10904 XML_SetUserData(g_parser, options);
10905 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
10906 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
10907 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10908 != XML_STATUS_ERROR)
10909 break;
10910 /* See comment in test_nsalloc_xmlns() */
10911 nsalloc_teardown();
10912 nsalloc_setup();
10913 }
10914 if (i == 0)
10915 fail("Parsing worked despite failing reallocations");
10916 else if (i == max_realloc_count)
10917 fail("Parsing failed even at max reallocation count");
10918 }
10919
START_TEST(test_nsalloc_realloc_long_context)10920 START_TEST(test_nsalloc_realloc_long_context) {
10921 const char *text
10922 = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10923 " <!ENTITY en SYSTEM 'bar'>\n"
10924 "]>\n"
10925 "<doc xmlns='http://example.org/"
10926 /* 64 characters per line */
10927 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10928 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10929 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10930 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10931 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10932 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10933 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10934 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10935 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10936 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10937 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10938 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10939 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10940 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10941 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10942 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKL"
10943 "'>\n"
10944 "&en;"
10945 "</doc>";
10946
10947 context_realloc_test(text);
10948 }
10949 END_TEST
10950
START_TEST(test_nsalloc_realloc_long_context_2)10951 START_TEST(test_nsalloc_realloc_long_context_2) {
10952 const char *text
10953 = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10954 " <!ENTITY en SYSTEM 'bar'>\n"
10955 "]>\n"
10956 "<doc xmlns='http://example.org/"
10957 /* 64 characters per line */
10958 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10959 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10960 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10961 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10962 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10963 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10964 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10965 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10966 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10967 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10968 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10969 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10970 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10971 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10972 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10973 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJK"
10974 "'>\n"
10975 "&en;"
10976 "</doc>";
10977
10978 context_realloc_test(text);
10979 }
10980 END_TEST
10981
START_TEST(test_nsalloc_realloc_long_context_3)10982 START_TEST(test_nsalloc_realloc_long_context_3) {
10983 const char *text
10984 = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10985 " <!ENTITY en SYSTEM 'bar'>\n"
10986 "]>\n"
10987 "<doc xmlns='http://example.org/"
10988 /* 64 characters per line */
10989 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10990 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10991 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10992 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10993 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10994 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10995 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10996 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10997 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10998 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10999 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11000 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11001 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11002 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11003 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11004 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGH"
11005 "'>\n"
11006 "&en;"
11007 "</doc>";
11008
11009 context_realloc_test(text);
11010 }
11011 END_TEST
11012
START_TEST(test_nsalloc_realloc_long_context_4)11013 START_TEST(test_nsalloc_realloc_long_context_4) {
11014 const char *text
11015 = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11016 " <!ENTITY en SYSTEM 'bar'>\n"
11017 "]>\n"
11018 "<doc xmlns='http://example.org/"
11019 /* 64 characters per line */
11020 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11021 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11022 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11023 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11024 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11025 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11026 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11027 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11028 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11029 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11030 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11031 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11032 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11033 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11034 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11035 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO"
11036 "'>\n"
11037 "&en;"
11038 "</doc>";
11039
11040 context_realloc_test(text);
11041 }
11042 END_TEST
11043
START_TEST(test_nsalloc_realloc_long_context_5)11044 START_TEST(test_nsalloc_realloc_long_context_5) {
11045 const char *text
11046 = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11047 " <!ENTITY en SYSTEM 'bar'>\n"
11048 "]>\n"
11049 "<doc xmlns='http://example.org/"
11050 /* 64 characters per line */
11051 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11052 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11053 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11054 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11055 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11056 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11057 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11058 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11059 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11060 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11061 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11062 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11063 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11064 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11065 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11066 "ABC"
11067 "'>\n"
11068 "&en;"
11069 "</doc>";
11070
11071 context_realloc_test(text);
11072 }
11073 END_TEST
11074
START_TEST(test_nsalloc_realloc_long_context_6)11075 START_TEST(test_nsalloc_realloc_long_context_6) {
11076 const char *text
11077 = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11078 " <!ENTITY en SYSTEM 'bar'>\n"
11079 "]>\n"
11080 "<doc xmlns='http://example.org/"
11081 /* 64 characters per line */
11082 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11083 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11084 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11085 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11086 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11087 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11088 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11089 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11090 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11091 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11092 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11093 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11094 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11095 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11096 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
11097 "'>\n"
11098 "&en;"
11099 "</doc>";
11100
11101 context_realloc_test(text);
11102 }
11103 END_TEST
11104
START_TEST(test_nsalloc_realloc_long_context_7)11105 START_TEST(test_nsalloc_realloc_long_context_7) {
11106 const char *text
11107 = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11108 " <!ENTITY en SYSTEM 'bar'>\n"
11109 "]>\n"
11110 "<doc xmlns='http://example.org/"
11111 /* 64 characters per line */
11112 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11113 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11114 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11115 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11116 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11117 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11118 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11119 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11120 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11121 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11122 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11123 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11124 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11125 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11126 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11127 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLM"
11128 "'>\n"
11129 "&en;"
11130 "</doc>";
11131
11132 context_realloc_test(text);
11133 }
11134 END_TEST
11135
START_TEST(test_nsalloc_realloc_long_ge_name)11136 START_TEST(test_nsalloc_realloc_long_ge_name) {
11137 const char *text
11138 = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11139 " <!ENTITY "
11140 /* 64 characters per line */
11141 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11142 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11143 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11144 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11145 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11146 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11147 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11148 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11149 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11150 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11151 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11152 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11153 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11154 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11155 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11156 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11157 " SYSTEM 'bar'>\n"
11158 "]>\n"
11159 "<doc xmlns='http://example.org/baz'>\n"
11160 "&"
11161 /* 64 characters per line */
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 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11176 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11177 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11178 ";"
11179 "</doc>";
11180 ExtOption options[] = {
11181 {XCS("foo"), "<!ELEMENT el EMPTY>"}, {XCS("bar"), "<el/>"}, {NULL, NULL}};
11182 int i;
11183 const int max_realloc_count = 10;
11184
11185 for (i = 0; i < max_realloc_count; i++) {
11186 reallocation_count = i;
11187 XML_SetUserData(g_parser, options);
11188 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11189 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11190 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
11191 != XML_STATUS_ERROR)
11192 break;
11193 /* See comment in test_nsalloc_xmlns() */
11194 nsalloc_teardown();
11195 nsalloc_setup();
11196 }
11197 if (i == 0)
11198 fail("Parsing worked despite failing reallocations");
11199 else if (i == max_realloc_count)
11200 fail("Parsing failed even at max reallocation count");
11201 }
11202 END_TEST
11203
11204 /* Test that when a namespace is passed through the context mechanism
11205 * to an external entity parser, the parsers handle reallocation
11206 * failures correctly. The prefix is exactly the right length to
11207 * provoke particular uncommon code paths.
11208 */
START_TEST(test_nsalloc_realloc_long_context_in_dtd)11209 START_TEST(test_nsalloc_realloc_long_context_in_dtd) {
11210 const char *text1
11211 = "<!DOCTYPE "
11212 /* 64 characters per line */
11213 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11214 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11215 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11216 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11217 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11218 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11219 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11220 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11221 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11222 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11223 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11224 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11225 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11226 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11227 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11228 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11229 ":doc [\n"
11230 " <!ENTITY First SYSTEM 'foo/First'>\n"
11231 "]>\n"
11232 "<"
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 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11248 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11249 ":doc xmlns:"
11250 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
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 "='foo/Second'>&First;";
11267 const char *text2
11268 = "</"
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 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11285 ":doc>";
11286 ExtOption options[] = {{XCS("foo/First"), "Hello world"}, {NULL, NULL}};
11287 int i;
11288 const int max_realloc_count = 20;
11289
11290 for (i = 0; i < max_realloc_count; i++) {
11291 reallocation_count = i;
11292 XML_SetUserData(g_parser, options);
11293 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11294 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11295 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
11296 != XML_STATUS_ERROR
11297 && _XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2),
11298 XML_TRUE)
11299 != XML_STATUS_ERROR)
11300 break;
11301 /* See comment in test_nsalloc_xmlns() */
11302 nsalloc_teardown();
11303 nsalloc_setup();
11304 }
11305 if (i == 0)
11306 fail("Parsing worked despite failing reallocations");
11307 else if (i == max_realloc_count)
11308 fail("Parsing failed even at max reallocation count");
11309 }
11310 END_TEST
11311
START_TEST(test_nsalloc_long_default_in_ext)11312 START_TEST(test_nsalloc_long_default_in_ext) {
11313 const char *text
11314 = "<!DOCTYPE doc [\n"
11315 " <!ATTLIST e a1 CDATA '"
11316 /* 64 characters per line */
11317 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11318 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11319 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11320 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11321 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11322 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11323 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11324 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11325 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11326 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11327 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11328 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11329 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11330 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11331 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11332 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11333 "'>\n"
11334 " <!ENTITY x SYSTEM 'foo'>\n"
11335 "]>\n"
11336 "<doc>&x;</doc>";
11337 ExtOption options[] = {{XCS("foo"), "<e/>"}, {NULL, NULL}};
11338 int i;
11339 const int max_alloc_count = 50;
11340
11341 for (i = 0; i < max_alloc_count; i++) {
11342 allocation_count = i;
11343 XML_SetUserData(g_parser, options);
11344 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11345 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11346 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
11347 != XML_STATUS_ERROR)
11348 break;
11349
11350 /* See comment in test_nsalloc_xmlns() */
11351 nsalloc_teardown();
11352 nsalloc_setup();
11353 }
11354 if (i == 0)
11355 fail("Parsing worked despite failing allocations");
11356 else if (i == max_alloc_count)
11357 fail("Parsing failed even at max allocation count");
11358 }
11359 END_TEST
11360
START_TEST(test_nsalloc_long_systemid_in_ext)11361 START_TEST(test_nsalloc_long_systemid_in_ext) {
11362 const char *text
11363 = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11364 " <!ENTITY en SYSTEM '"
11365 /* 64 characters per line */
11366 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11367 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11368 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11369 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11370 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11371 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11372 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11373 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11374 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11375 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11376 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11377 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11378 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11379 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11380 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11381 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11382 "'>\n"
11383 "]>\n"
11384 "<doc>&en;</doc>";
11385 ExtOption options[] = {
11386 {XCS("foo"), "<!ELEMENT e EMPTY>"},
11387 {/* clang-format off */
11388 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11389 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11390 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11391 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11392 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11393 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11394 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11395 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11396 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11397 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11398 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11399 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11400 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11401 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11402 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11403 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"),
11404 /* clang-format on */
11405 "<e/>"},
11406 {NULL, NULL}};
11407 int i;
11408 const int max_alloc_count = 55;
11409
11410 for (i = 0; i < max_alloc_count; i++) {
11411 allocation_count = i;
11412 XML_SetUserData(g_parser, options);
11413 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11414 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11415 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
11416 != XML_STATUS_ERROR)
11417 break;
11418
11419 /* See comment in test_nsalloc_xmlns() */
11420 nsalloc_teardown();
11421 nsalloc_setup();
11422 }
11423 if (i == 0)
11424 fail("Parsing worked despite failing allocations");
11425 else if (i == max_alloc_count)
11426 fail("Parsing failed even at max allocation count");
11427 }
11428 END_TEST
11429
11430 /* Test the effects of allocation failure on parsing an element in a
11431 * namespace. Based on test_nsalloc_long_context.
11432 */
START_TEST(test_nsalloc_prefixed_element)11433 START_TEST(test_nsalloc_prefixed_element) {
11434 const char *text = "<!DOCTYPE pfx:element SYSTEM 'foo' [\n"
11435 " <!ATTLIST pfx:element baz ID #REQUIRED>\n"
11436 " <!ENTITY en SYSTEM 'bar'>\n"
11437 "]>\n"
11438 "<pfx:element xmlns:pfx='http://example.org/' baz='2'>\n"
11439 "&en;"
11440 "</pfx:element>";
11441 ExtOption options[] = {
11442 {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}};
11443 int i;
11444 const int max_alloc_count = 70;
11445
11446 for (i = 0; i < max_alloc_count; i++) {
11447 allocation_count = i;
11448 XML_SetUserData(g_parser, options);
11449 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11450 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11451 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
11452 != XML_STATUS_ERROR)
11453 break;
11454
11455 /* See comment in test_nsalloc_xmlns() */
11456 nsalloc_teardown();
11457 nsalloc_setup();
11458 }
11459 if (i == 0)
11460 fail("Success despite failing allocator");
11461 else if (i == max_alloc_count)
11462 fail("Failed even at full allocation count");
11463 }
11464 END_TEST
11465
11466 #if defined(XML_DTD)
11467 typedef enum XML_Status (*XmlParseFunction)(XML_Parser, const char *, int, int);
11468
11469 struct AccountingTestCase {
11470 const char *primaryText;
11471 const char *firstExternalText; /* often NULL */
11472 const char *secondExternalText; /* often NULL */
11473 const unsigned long long expectedCountBytesIndirectExtra;
11474 XML_Bool singleBytesWanted;
11475 };
11476
11477 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)11478 accounting_external_entity_ref_handler(XML_Parser parser,
11479 const XML_Char *context,
11480 const XML_Char *base,
11481 const XML_Char *systemId,
11482 const XML_Char *publicId) {
11483 UNUSED_P(context);
11484 UNUSED_P(base);
11485 UNUSED_P(publicId);
11486
11487 const struct AccountingTestCase *const testCase
11488 = (const struct AccountingTestCase *)XML_GetUserData(parser);
11489
11490 const char *externalText = NULL;
11491 if (xcstrcmp(systemId, XCS("first.ent")) == 0) {
11492 externalText = testCase->firstExternalText;
11493 } else if (xcstrcmp(systemId, XCS("second.ent")) == 0) {
11494 externalText = testCase->secondExternalText;
11495 } else {
11496 assert(! "systemId is neither \"first.ent\" nor \"second.ent\"");
11497 }
11498 assert(externalText);
11499
11500 XML_Parser entParser = XML_ExternalEntityParserCreate(parser, context, 0);
11501 assert(entParser);
11502
11503 const XmlParseFunction xmlParseFunction
11504 = testCase->singleBytesWanted ? _XML_Parse_SINGLE_BYTES : XML_Parse;
11505
11506 const enum XML_Status status = xmlParseFunction(
11507 entParser, externalText, (int)strlen(externalText), XML_TRUE);
11508
11509 XML_ParserFree(entParser);
11510 return status;
11511 }
11512
START_TEST(test_accounting_precision)11513 START_TEST(test_accounting_precision) {
11514 const XML_Bool filled_later = XML_TRUE; /* value is arbitrary */
11515 struct AccountingTestCase cases[] = {
11516 {"<e/>", NULL, NULL, 0, 0},
11517 {"<e></e>", NULL, NULL, 0, 0},
11518
11519 /* Attributes */
11520 {"<e k1=\"v2\" k2=\"v2\"/>", NULL, NULL, 0, filled_later},
11521 {"<e k1=\"v2\" k2=\"v2\"></e>", NULL, NULL, 0, 0},
11522 {"<p:e xmlns:p=\"https://domain.invalid/\" />", NULL, NULL, 0,
11523 filled_later},
11524 {"<e k=\"&'><"\" />", NULL, NULL,
11525 sizeof(XML_Char) * 5 /* number of predefined entities */, filled_later},
11526 {"<e1 xmlns='https://example.org/'>\n"
11527 " <e2 xmlns=''/>\n"
11528 "</e1>",
11529 NULL, NULL, 0, filled_later},
11530
11531 /* Text */
11532 {"<e>text</e>", NULL, NULL, 0, filled_later},
11533 {"<e1><e2>text1<e3/>text2</e2></e1>", NULL, NULL, 0, filled_later},
11534 {"<e>&'><"</e>", NULL, NULL,
11535 sizeof(XML_Char) * 5 /* number of predefined entities */, filled_later},
11536 {"<e>A)</e>", NULL, NULL, 0, filled_later},
11537
11538 /* Prolog */
11539 {"<?xml version=\"1.0\"?><root/>", NULL, NULL, 0, filled_later},
11540
11541 /* Whitespace */
11542 {" <e1> <e2> </e2> </e1> ", NULL, NULL, 0, filled_later},
11543 {"<e1 ><e2 /></e1 >", NULL, NULL, 0, filled_later},
11544 {"<e1><e2 k = \"v\"/><e3 k = 'v'/></e1>", NULL, NULL, 0, filled_later},
11545
11546 /* Comments */
11547 {"<!-- Comment --><e><!-- Comment --></e>", NULL, NULL, 0, filled_later},
11548
11549 /* Processing instructions */
11550 {"<?xml-stylesheet type=\"text/xsl\" href=\"https://domain.invalid/\" media=\"all\"?><e/>",
11551 NULL, NULL, 0, filled_later},
11552 {"<?pi0?><?pi1 ?><?pi2 ?><!DOCTYPE r SYSTEM 'first.ent'><r/>",
11553 "<?pi3?><!ENTITY % e1 SYSTEM 'second.ent'><?pi4?>%e1;<?pi5?>", "<?pi6?>",
11554 0, filled_later},
11555
11556 /* CDATA */
11557 {"<e><![CDATA[one two three]]></e>", NULL, NULL, 0, filled_later},
11558 /* The following is the essence of this OSS-Fuzz finding:
11559 https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=34302
11560 https://oss-fuzz.com/testcase-detail/4860575394955264
11561 */
11562 {"<!DOCTYPE r [\n"
11563 "<!ENTITY e \"111<![CDATA[2 <= 2]]>333\">\n"
11564 "]>\n"
11565 "<r>&e;</r>\n",
11566 NULL, NULL, sizeof(XML_Char) * strlen("111<![CDATA[2 <= 2]]>333"),
11567 filled_later},
11568
11569 /* Conditional sections */
11570 {"<!DOCTYPE r [\n"
11571 "<!ENTITY % draft 'INCLUDE'>\n"
11572 "<!ENTITY % final 'IGNORE'>\n"
11573 "<!ENTITY % import SYSTEM \"first.ent\">\n"
11574 "%import;\n"
11575 "]>\n"
11576 "<r/>\n",
11577 "<![%draft;[<!--1-->]]>\n"
11578 "<![%final;[<!--22-->]]>",
11579 NULL, sizeof(XML_Char) * (strlen("INCLUDE") + strlen("IGNORE")),
11580 filled_later},
11581
11582 /* General entities */
11583 {"<!DOCTYPE root [\n"
11584 "<!ENTITY nine \"123456789\">\n"
11585 "]>\n"
11586 "<root>&nine;</root>",
11587 NULL, NULL, sizeof(XML_Char) * strlen("123456789"), filled_later},
11588 {"<!DOCTYPE root [\n"
11589 "<!ENTITY nine \"123456789\">\n"
11590 "]>\n"
11591 "<root k1=\"&nine;\"/>",
11592 NULL, NULL, sizeof(XML_Char) * strlen("123456789"), filled_later},
11593 {"<!DOCTYPE root [\n"
11594 "<!ENTITY nine \"123456789\">\n"
11595 "<!ENTITY nine2 \"&nine;&nine;\">\n"
11596 "]>\n"
11597 "<root>&nine2;&nine2;&nine2;</root>",
11598 NULL, NULL,
11599 sizeof(XML_Char) * 3 /* calls to &nine2; */ * 2 /* calls to &nine; */
11600 * (strlen("&nine;") + strlen("123456789")),
11601 filled_later},
11602 {"<!DOCTYPE r [\n"
11603 " <!ENTITY five SYSTEM 'first.ent'>\n"
11604 "]>\n"
11605 "<r>&five;</r>",
11606 "12345", NULL, 0, filled_later},
11607
11608 /* Parameter entities */
11609 {"<!DOCTYPE r [\n"
11610 "<!ENTITY % comment \"<!---->\">\n"
11611 "%comment;\n"
11612 "]>\n"
11613 "<r/>",
11614 NULL, NULL, sizeof(XML_Char) * strlen("<!---->"), filled_later},
11615 {"<!DOCTYPE r [\n"
11616 "<!ENTITY % ninedef \"<!ENTITY nine "123456789">\">\n"
11617 "%ninedef;\n"
11618 "]>\n"
11619 "<r>&nine;</r>",
11620 NULL, NULL,
11621 sizeof(XML_Char)
11622 * (strlen("<!ENTITY nine \"123456789\">") + strlen("123456789")),
11623 filled_later},
11624 {"<!DOCTYPE r [\n"
11625 "<!ENTITY % comment \"<!--1-->\">\n"
11626 "<!ENTITY % comment2 \"%comment;<!--22-->%comment;\">\n"
11627 "%comment2;\n"
11628 "]>\n"
11629 "<r/>\n",
11630 NULL, NULL,
11631 sizeof(XML_Char)
11632 * (strlen("%comment;<!--22-->%comment;") + 2 * strlen("<!--1-->")),
11633 filled_later},
11634 {"<!DOCTYPE r [\n"
11635 " <!ENTITY % five \"12345\">\n"
11636 " <!ENTITY % five2def \"<!ENTITY five2 "[%five;][%five;]]]]">\">\n"
11637 " %five2def;\n"
11638 "]>\n"
11639 "<r>&five2;</r>",
11640 NULL, NULL, /* from "%five2def;": */
11641 sizeof(XML_Char)
11642 * (strlen("<!ENTITY five2 \"[%five;][%five;]]]]\">")
11643 + 2 /* calls to "%five;" */ * strlen("12345")
11644 + /* from "&five2;": */ strlen("[12345][12345]]]]")),
11645 filled_later},
11646 {"<!DOCTYPE r SYSTEM \"first.ent\">\n"
11647 "<r/>",
11648 "<!ENTITY % comment '<!--1-->'>\n"
11649 "<!ENTITY % comment2 '<!--22-->%comment;<!--22-->%comment;<!--22-->'>\n"
11650 "%comment2;",
11651 NULL,
11652 sizeof(XML_Char)
11653 * (strlen("<!--22-->%comment;<!--22-->%comment;<!--22-->")
11654 + 2 /* calls to "%comment;" */ * strlen("<!---->")),
11655 filled_later},
11656 {"<!DOCTYPE r SYSTEM 'first.ent'>\n"
11657 "<r/>",
11658 "<!ENTITY % e1 PUBLIC 'foo' 'second.ent'>\n"
11659 "<!ENTITY % e2 '<!--22-->%e1;<!--22-->'>\n"
11660 "%e2;\n",
11661 "<!--1-->", sizeof(XML_Char) * strlen("<!--22--><!--1--><!--22-->"),
11662 filled_later},
11663 {
11664 "<!DOCTYPE r SYSTEM 'first.ent'>\n"
11665 "<r/>",
11666 "<!ENTITY % e1 SYSTEM 'second.ent'>\n"
11667 "<!ENTITY % e2 '%e1;'>",
11668 "<?xml version='1.0' encoding='utf-8'?>\n"
11669 "hello\n"
11670 "xml" /* without trailing newline! */,
11671 0,
11672 filled_later,
11673 },
11674 {
11675 "<!DOCTYPE r SYSTEM 'first.ent'>\n"
11676 "<r/>",
11677 "<!ENTITY % e1 SYSTEM 'second.ent'>\n"
11678 "<!ENTITY % e2 '%e1;'>",
11679 "<?xml version='1.0' encoding='utf-8'?>\n"
11680 "hello\n"
11681 "xml\n" /* with trailing newline! */,
11682 0,
11683 filled_later,
11684 },
11685 {"<!DOCTYPE doc SYSTEM 'first.ent'>\n"
11686 "<doc></doc>\n",
11687 "<!ELEMENT doc EMPTY>\n"
11688 "<!ENTITY % e1 SYSTEM 'second.ent'>\n"
11689 "<!ENTITY % e2 '%e1;'>\n"
11690 "%e1;\n",
11691 "\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>" /* UTF-8 BOM */,
11692 strlen("\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>"), filled_later},
11693 {"<!DOCTYPE r [\n"
11694 " <!ENTITY five SYSTEM 'first.ent'>\n"
11695 "]>\n"
11696 "<r>&five;</r>",
11697 "\xEF\xBB\xBF" /* UTF-8 BOM */, NULL, 0, filled_later},
11698 };
11699
11700 const size_t countCases = sizeof(cases) / sizeof(cases[0]);
11701 size_t u = 0;
11702 for (; u < countCases; u++) {
11703 size_t v = 0;
11704 for (; v < 2; v++) {
11705 const XML_Bool singleBytesWanted = (v == 0) ? XML_FALSE : XML_TRUE;
11706 const unsigned long long expectedCountBytesDirect
11707 = strlen(cases[u].primaryText);
11708 const unsigned long long expectedCountBytesIndirect
11709 = (cases[u].firstExternalText ? strlen(cases[u].firstExternalText)
11710 : 0)
11711 + (cases[u].secondExternalText ? strlen(cases[u].secondExternalText)
11712 : 0)
11713 + cases[u].expectedCountBytesIndirectExtra;
11714
11715 XML_Parser parser = XML_ParserCreate(NULL);
11716 XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11717 if (cases[u].firstExternalText) {
11718 XML_SetExternalEntityRefHandler(parser,
11719 accounting_external_entity_ref_handler);
11720 XML_SetUserData(parser, (void *)&cases[u]);
11721 cases[u].singleBytesWanted = singleBytesWanted;
11722 }
11723
11724 const XmlParseFunction xmlParseFunction
11725 = singleBytesWanted ? _XML_Parse_SINGLE_BYTES : XML_Parse;
11726
11727 enum XML_Status status
11728 = xmlParseFunction(parser, cases[u].primaryText,
11729 (int)strlen(cases[u].primaryText), XML_TRUE);
11730 if (status != XML_STATUS_OK) {
11731 _xml_failure(parser, __FILE__, __LINE__);
11732 }
11733
11734 const unsigned long long actualCountBytesDirect
11735 = testingAccountingGetCountBytesDirect(parser);
11736 const unsigned long long actualCountBytesIndirect
11737 = testingAccountingGetCountBytesIndirect(parser);
11738
11739 XML_ParserFree(parser);
11740
11741 if (actualCountBytesDirect != expectedCountBytesDirect) {
11742 fprintf(
11743 stderr,
11744 "Document " EXPAT_FMT_SIZE_T("") " of " EXPAT_FMT_SIZE_T("") ", %s: Expected " EXPAT_FMT_ULL(
11745 "") " count direct bytes, got " EXPAT_FMT_ULL("") " instead.\n",
11746 u + 1, countCases, singleBytesWanted ? "single bytes" : "chunks",
11747 expectedCountBytesDirect, actualCountBytesDirect);
11748 fail("Count of direct bytes is off");
11749 }
11750
11751 if (actualCountBytesIndirect != expectedCountBytesIndirect) {
11752 fprintf(
11753 stderr,
11754 "Document " EXPAT_FMT_SIZE_T("") " of " EXPAT_FMT_SIZE_T("") ", %s: Expected " EXPAT_FMT_ULL(
11755 "") " count indirect bytes, got " EXPAT_FMT_ULL("") " instead.\n",
11756 u + 1, countCases, singleBytesWanted ? "single bytes" : "chunks",
11757 expectedCountBytesIndirect, actualCountBytesIndirect);
11758 fail("Count of indirect bytes is off");
11759 }
11760 }
11761 }
11762 }
11763 END_TEST
11764
START_TEST(test_billion_laughs_attack_protection_api)11765 START_TEST(test_billion_laughs_attack_protection_api) {
11766 XML_Parser parserWithoutParent = XML_ParserCreate(NULL);
11767 XML_Parser parserWithParent
11768 = XML_ExternalEntityParserCreate(parserWithoutParent, NULL, NULL);
11769 if (parserWithoutParent == NULL)
11770 fail("parserWithoutParent is NULL");
11771 if (parserWithParent == NULL)
11772 fail("parserWithParent is NULL");
11773
11774 // XML_SetBillionLaughsAttackProtectionMaximumAmplification, error cases
11775 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(NULL, 123.0f)
11776 == XML_TRUE)
11777 fail("Call with NULL parser is NOT supposed to succeed");
11778 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(parserWithParent,
11779 123.0f)
11780 == XML_TRUE)
11781 fail("Call with non-root parser is NOT supposed to succeed");
11782 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
11783 parserWithoutParent, NAN)
11784 == XML_TRUE)
11785 fail("Call with NaN limit is NOT supposed to succeed");
11786 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
11787 parserWithoutParent, -1.0f)
11788 == XML_TRUE)
11789 fail("Call with negative limit is NOT supposed to succeed");
11790 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
11791 parserWithoutParent, 0.9f)
11792 == XML_TRUE)
11793 fail("Call with positive limit <1.0 is NOT supposed to succeed");
11794
11795 // XML_SetBillionLaughsAttackProtectionMaximumAmplification, success cases
11796 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
11797 parserWithoutParent, 1.0f)
11798 == XML_FALSE)
11799 fail("Call with positive limit >=1.0 is supposed to succeed");
11800 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
11801 parserWithoutParent, 123456.789f)
11802 == XML_FALSE)
11803 fail("Call with positive limit >=1.0 is supposed to succeed");
11804 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
11805 parserWithoutParent, INFINITY)
11806 == XML_FALSE)
11807 fail("Call with positive limit >=1.0 is supposed to succeed");
11808
11809 // XML_SetBillionLaughsAttackProtectionActivationThreshold, error cases
11810 if (XML_SetBillionLaughsAttackProtectionActivationThreshold(NULL, 123)
11811 == XML_TRUE)
11812 fail("Call with NULL parser is NOT supposed to succeed");
11813 if (XML_SetBillionLaughsAttackProtectionActivationThreshold(parserWithParent,
11814 123)
11815 == XML_TRUE)
11816 fail("Call with non-root parser is NOT supposed to succeed");
11817
11818 // XML_SetBillionLaughsAttackProtectionActivationThreshold, success cases
11819 if (XML_SetBillionLaughsAttackProtectionActivationThreshold(
11820 parserWithoutParent, 123)
11821 == XML_FALSE)
11822 fail("Call with non-NULL parentless parser is supposed to succeed");
11823
11824 XML_ParserFree(parserWithParent);
11825 XML_ParserFree(parserWithoutParent);
11826 }
11827 END_TEST
11828
START_TEST(test_helper_unsigned_char_to_printable)11829 START_TEST(test_helper_unsigned_char_to_printable) {
11830 // Smoke test
11831 unsigned char uc = 0;
11832 for (; uc < (unsigned char)-1; uc++) {
11833 const char *const printable = unsignedCharToPrintable(uc);
11834 if (printable == NULL)
11835 fail("unsignedCharToPrintable returned NULL");
11836 if (strlen(printable) < (size_t)1)
11837 fail("unsignedCharToPrintable returned empty string");
11838 }
11839
11840 // Two concrete samples
11841 if (strcmp(unsignedCharToPrintable('A'), "A") != 0)
11842 fail("unsignedCharToPrintable result mistaken");
11843 if (strcmp(unsignedCharToPrintable('\\'), "\\\\") != 0)
11844 fail("unsignedCharToPrintable result mistaken");
11845 }
11846 END_TEST
11847 #endif // defined(XML_DTD)
11848
11849 static Suite *
make_suite(void)11850 make_suite(void) {
11851 Suite *s = suite_create("basic");
11852 TCase *tc_basic = tcase_create("basic tests");
11853 TCase *tc_namespace = tcase_create("XML namespaces");
11854 TCase *tc_misc = tcase_create("miscellaneous tests");
11855 TCase *tc_alloc = tcase_create("allocation tests");
11856 TCase *tc_nsalloc = tcase_create("namespace allocation tests");
11857 #if defined(XML_DTD)
11858 TCase *tc_accounting = tcase_create("accounting tests");
11859 #endif
11860
11861 suite_add_tcase(s, tc_basic);
11862 tcase_add_checked_fixture(tc_basic, basic_setup, basic_teardown);
11863 tcase_add_test(tc_basic, test_nul_byte);
11864 tcase_add_test(tc_basic, test_u0000_char);
11865 tcase_add_test(tc_basic, test_siphash_self);
11866 tcase_add_test(tc_basic, test_siphash_spec);
11867 tcase_add_test(tc_basic, test_bom_utf8);
11868 tcase_add_test(tc_basic, test_bom_utf16_be);
11869 tcase_add_test(tc_basic, test_bom_utf16_le);
11870 tcase_add_test(tc_basic, test_nobom_utf16_le);
11871 tcase_add_test(tc_basic, test_illegal_utf8);
11872 tcase_add_test(tc_basic, test_utf8_auto_align);
11873 tcase_add_test(tc_basic, test_utf16);
11874 tcase_add_test(tc_basic, test_utf16_le_epilog_newline);
11875 tcase_add_test(tc_basic, test_not_utf16);
11876 tcase_add_test(tc_basic, test_bad_encoding);
11877 tcase_add_test(tc_basic, test_latin1_umlauts);
11878 tcase_add_test(tc_basic, test_long_utf8_character);
11879 tcase_add_test(tc_basic, test_long_latin1_attribute);
11880 tcase_add_test(tc_basic, test_long_ascii_attribute);
11881 /* Regression test for SF bug #491986. */
11882 tcase_add_test(tc_basic, test_danish_latin1);
11883 /* Regression test for SF bug #514281. */
11884 tcase_add_test(tc_basic, test_french_charref_hexidecimal);
11885 tcase_add_test(tc_basic, test_french_charref_decimal);
11886 tcase_add_test(tc_basic, test_french_latin1);
11887 tcase_add_test(tc_basic, test_french_utf8);
11888 tcase_add_test(tc_basic, test_utf8_false_rejection);
11889 tcase_add_test(tc_basic, test_line_number_after_parse);
11890 tcase_add_test(tc_basic, test_column_number_after_parse);
11891 tcase_add_test(tc_basic, test_line_and_column_numbers_inside_handlers);
11892 tcase_add_test(tc_basic, test_line_number_after_error);
11893 tcase_add_test(tc_basic, test_column_number_after_error);
11894 tcase_add_test(tc_basic, test_really_long_lines);
11895 tcase_add_test(tc_basic, test_really_long_encoded_lines);
11896 tcase_add_test(tc_basic, test_end_element_events);
11897 tcase_add_test(tc_basic, test_attr_whitespace_normalization);
11898 tcase_add_test(tc_basic, test_xmldecl_misplaced);
11899 tcase_add_test(tc_basic, test_xmldecl_invalid);
11900 tcase_add_test(tc_basic, test_xmldecl_missing_attr);
11901 tcase_add_test(tc_basic, test_xmldecl_missing_value);
11902 tcase_add_test(tc_basic, test_unknown_encoding_internal_entity);
11903 tcase_add_test(tc_basic, test_unrecognised_encoding_internal_entity);
11904 tcase_add_test(tc_basic, test_wfc_undeclared_entity_unread_external_subset);
11905 tcase_add_test(tc_basic, test_wfc_undeclared_entity_no_external_subset);
11906 tcase_add_test(tc_basic, test_wfc_undeclared_entity_standalone);
11907 tcase_add_test(tc_basic, test_wfc_undeclared_entity_with_external_subset);
11908 tcase_add_test(tc_basic, test_not_standalone_handler_reject);
11909 tcase_add_test(tc_basic, test_not_standalone_handler_accept);
11910 tcase_add_test(tc_basic,
11911 test_wfc_undeclared_entity_with_external_subset_standalone);
11912 tcase_add_test(tc_basic, test_entity_with_external_subset_unless_standalone);
11913 tcase_add_test(tc_basic, test_wfc_no_recursive_entity_refs);
11914 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_set_encoding);
11915 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_no_handler);
11916 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_set_bom);
11917 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_bad_encoding);
11918 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_bad_encoding_2);
11919 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_invalid_parse);
11920 tcase_add_test__ifdef_xml_dtd(tc_basic,
11921 test_ext_entity_invalid_suspended_parse);
11922 tcase_add_test(tc_basic, test_dtd_default_handling);
11923 tcase_add_test(tc_basic, test_dtd_attr_handling);
11924 tcase_add_test(tc_basic, test_empty_ns_without_namespaces);
11925 tcase_add_test(tc_basic, test_ns_in_attribute_default_without_namespaces);
11926 tcase_add_test(tc_basic, test_stop_parser_between_char_data_calls);
11927 tcase_add_test(tc_basic, test_suspend_parser_between_char_data_calls);
11928 tcase_add_test(tc_basic, test_repeated_stop_parser_between_char_data_calls);
11929 tcase_add_test(tc_basic, test_good_cdata_ascii);
11930 tcase_add_test(tc_basic, test_good_cdata_utf16);
11931 tcase_add_test(tc_basic, test_good_cdata_utf16_le);
11932 tcase_add_test(tc_basic, test_long_cdata_utf16);
11933 tcase_add_test(tc_basic, test_multichar_cdata_utf16);
11934 tcase_add_test(tc_basic, test_utf16_bad_surrogate_pair);
11935 tcase_add_test(tc_basic, test_bad_cdata);
11936 tcase_add_test(tc_basic, test_bad_cdata_utf16);
11937 tcase_add_test(tc_basic, test_stop_parser_between_cdata_calls);
11938 tcase_add_test(tc_basic, test_suspend_parser_between_cdata_calls);
11939 tcase_add_test(tc_basic, test_memory_allocation);
11940 tcase_add_test(tc_basic, test_default_current);
11941 tcase_add_test(tc_basic, test_dtd_elements);
11942 tcase_add_test(tc_basic, test_dtd_elements_nesting);
11943 tcase_add_test__ifdef_xml_dtd(tc_basic, test_set_foreign_dtd);
11944 tcase_add_test__ifdef_xml_dtd(tc_basic, test_foreign_dtd_not_standalone);
11945 tcase_add_test__ifdef_xml_dtd(tc_basic, test_invalid_foreign_dtd);
11946 tcase_add_test__ifdef_xml_dtd(tc_basic, test_foreign_dtd_with_doctype);
11947 tcase_add_test__ifdef_xml_dtd(tc_basic,
11948 test_foreign_dtd_without_external_subset);
11949 tcase_add_test__ifdef_xml_dtd(tc_basic, test_empty_foreign_dtd);
11950 tcase_add_test(tc_basic, test_set_base);
11951 tcase_add_test(tc_basic, test_attributes);
11952 tcase_add_test(tc_basic, test_reset_in_entity);
11953 tcase_add_test(tc_basic, test_resume_invalid_parse);
11954 tcase_add_test(tc_basic, test_resume_resuspended);
11955 tcase_add_test(tc_basic, test_cdata_default);
11956 tcase_add_test(tc_basic, test_subordinate_reset);
11957 tcase_add_test(tc_basic, test_subordinate_suspend);
11958 tcase_add_test(tc_basic, test_subordinate_xdecl_suspend);
11959 tcase_add_test(tc_basic, test_subordinate_xdecl_abort);
11960 tcase_add_test(tc_basic, test_explicit_encoding);
11961 tcase_add_test(tc_basic, test_trailing_cr);
11962 tcase_add_test(tc_basic, test_ext_entity_trailing_cr);
11963 tcase_add_test(tc_basic, test_trailing_rsqb);
11964 tcase_add_test(tc_basic, test_ext_entity_trailing_rsqb);
11965 tcase_add_test(tc_basic, test_ext_entity_good_cdata);
11966 tcase_add_test__ifdef_xml_dtd(tc_basic, test_user_parameters);
11967 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_ref_parameter);
11968 tcase_add_test(tc_basic, test_empty_parse);
11969 tcase_add_test(tc_basic, test_get_buffer_1);
11970 tcase_add_test(tc_basic, test_get_buffer_2);
11971 #if defined(XML_CONTEXT_BYTES)
11972 tcase_add_test(tc_basic, test_get_buffer_3_overflow);
11973 #endif
11974 tcase_add_test(tc_basic, test_byte_info_at_end);
11975 tcase_add_test(tc_basic, test_byte_info_at_error);
11976 tcase_add_test(tc_basic, test_byte_info_at_cdata);
11977 tcase_add_test(tc_basic, test_predefined_entities);
11978 tcase_add_test__ifdef_xml_dtd(tc_basic, test_invalid_tag_in_dtd);
11979 tcase_add_test(tc_basic, test_not_predefined_entities);
11980 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section);
11981 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section_utf16);
11982 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section_utf16_be);
11983 tcase_add_test__ifdef_xml_dtd(tc_basic, test_bad_ignore_section);
11984 tcase_add_test__ifdef_xml_dtd(tc_basic, test_external_entity_values);
11985 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_not_standalone);
11986 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_value_abort);
11987 tcase_add_test(tc_basic, test_bad_public_doctype);
11988 tcase_add_test(tc_basic, test_attribute_enum_value);
11989 tcase_add_test(tc_basic, test_predefined_entity_redefinition);
11990 tcase_add_test__ifdef_xml_dtd(tc_basic, test_dtd_stop_processing);
11991 tcase_add_test(tc_basic, test_public_notation_no_sysid);
11992 tcase_add_test(tc_basic, test_nested_groups);
11993 tcase_add_test(tc_basic, test_group_choice);
11994 tcase_add_test(tc_basic, test_standalone_parameter_entity);
11995 tcase_add_test__ifdef_xml_dtd(tc_basic, test_skipped_parameter_entity);
11996 tcase_add_test__ifdef_xml_dtd(tc_basic,
11997 test_recursive_external_parameter_entity);
11998 tcase_add_test(tc_basic, test_undefined_ext_entity_in_external_dtd);
11999 tcase_add_test(tc_basic, test_suspend_xdecl);
12000 tcase_add_test(tc_basic, test_abort_epilog);
12001 tcase_add_test(tc_basic, test_abort_epilog_2);
12002 tcase_add_test(tc_basic, test_suspend_epilog);
12003 tcase_add_test(tc_basic, test_suspend_in_sole_empty_tag);
12004 tcase_add_test(tc_basic, test_unfinished_epilog);
12005 tcase_add_test(tc_basic, test_partial_char_in_epilog);
12006 tcase_add_test(tc_basic, test_hash_collision);
12007 tcase_add_test__ifdef_xml_dtd(tc_basic, test_suspend_resume_internal_entity);
12008 tcase_add_test__ifdef_xml_dtd(tc_basic, test_resume_entity_with_syntax_error);
12009 tcase_add_test__ifdef_xml_dtd(tc_basic, test_suspend_resume_parameter_entity);
12010 tcase_add_test(tc_basic, test_restart_on_error);
12011 tcase_add_test(tc_basic, test_reject_lt_in_attribute_value);
12012 tcase_add_test(tc_basic, test_reject_unfinished_param_in_att_value);
12013 tcase_add_test(tc_basic, test_trailing_cr_in_att_value);
12014 tcase_add_test(tc_basic, test_standalone_internal_entity);
12015 tcase_add_test(tc_basic, test_skipped_external_entity);
12016 tcase_add_test(tc_basic, test_skipped_null_loaded_ext_entity);
12017 tcase_add_test(tc_basic, test_skipped_unloaded_ext_entity);
12018 tcase_add_test__ifdef_xml_dtd(tc_basic, test_param_entity_with_trailing_cr);
12019 tcase_add_test(tc_basic, test_invalid_character_entity);
12020 tcase_add_test(tc_basic, test_invalid_character_entity_2);
12021 tcase_add_test(tc_basic, test_invalid_character_entity_3);
12022 tcase_add_test(tc_basic, test_invalid_character_entity_4);
12023 tcase_add_test(tc_basic, test_pi_handled_in_default);
12024 tcase_add_test(tc_basic, test_comment_handled_in_default);
12025 tcase_add_test(tc_basic, test_pi_yml);
12026 tcase_add_test(tc_basic, test_pi_xnl);
12027 tcase_add_test(tc_basic, test_pi_xmm);
12028 tcase_add_test(tc_basic, test_utf16_pi);
12029 tcase_add_test(tc_basic, test_utf16_be_pi);
12030 tcase_add_test(tc_basic, test_utf16_be_comment);
12031 tcase_add_test(tc_basic, test_utf16_le_comment);
12032 tcase_add_test(tc_basic, test_missing_encoding_conversion_fn);
12033 tcase_add_test(tc_basic, test_failing_encoding_conversion_fn);
12034 tcase_add_test(tc_basic, test_unknown_encoding_success);
12035 tcase_add_test(tc_basic, test_unknown_encoding_bad_name);
12036 tcase_add_test(tc_basic, test_unknown_encoding_bad_name_2);
12037 tcase_add_test(tc_basic, test_unknown_encoding_long_name_1);
12038 tcase_add_test(tc_basic, test_unknown_encoding_long_name_2);
12039 tcase_add_test(tc_basic, test_invalid_unknown_encoding);
12040 tcase_add_test(tc_basic, test_unknown_ascii_encoding_ok);
12041 tcase_add_test(tc_basic, test_unknown_ascii_encoding_fail);
12042 tcase_add_test(tc_basic, test_unknown_encoding_invalid_length);
12043 tcase_add_test(tc_basic, test_unknown_encoding_invalid_topbit);
12044 tcase_add_test(tc_basic, test_unknown_encoding_invalid_surrogate);
12045 tcase_add_test(tc_basic, test_unknown_encoding_invalid_high);
12046 tcase_add_test(tc_basic, test_unknown_encoding_invalid_attr_value);
12047 tcase_add_test(tc_basic, test_ext_entity_latin1_utf16le_bom);
12048 tcase_add_test(tc_basic, test_ext_entity_latin1_utf16be_bom);
12049 tcase_add_test(tc_basic, test_ext_entity_latin1_utf16le_bom2);
12050 tcase_add_test(tc_basic, test_ext_entity_latin1_utf16be_bom2);
12051 tcase_add_test(tc_basic, test_ext_entity_utf16_be);
12052 tcase_add_test(tc_basic, test_ext_entity_utf16_le);
12053 tcase_add_test(tc_basic, test_ext_entity_utf16_unknown);
12054 tcase_add_test(tc_basic, test_ext_entity_utf8_non_bom);
12055 tcase_add_test(tc_basic, test_utf8_in_cdata_section);
12056 tcase_add_test(tc_basic, test_utf8_in_cdata_section_2);
12057 tcase_add_test(tc_basic, test_utf8_in_start_tags);
12058 tcase_add_test(tc_basic, test_trailing_spaces_in_elements);
12059 tcase_add_test(tc_basic, test_utf16_attribute);
12060 tcase_add_test(tc_basic, test_utf16_second_attr);
12061 tcase_add_test(tc_basic, test_attr_after_solidus);
12062 tcase_add_test__ifdef_xml_dtd(tc_basic, test_utf16_pe);
12063 tcase_add_test(tc_basic, test_bad_attr_desc_keyword);
12064 tcase_add_test(tc_basic, test_bad_attr_desc_keyword_utf16);
12065 tcase_add_test(tc_basic, test_bad_doctype);
12066 tcase_add_test(tc_basic, test_bad_doctype_utf8);
12067 tcase_add_test(tc_basic, test_bad_doctype_utf16);
12068 tcase_add_test(tc_basic, test_bad_doctype_plus);
12069 tcase_add_test(tc_basic, test_bad_doctype_star);
12070 tcase_add_test(tc_basic, test_bad_doctype_query);
12071 tcase_add_test__ifdef_xml_dtd(tc_basic, test_unknown_encoding_bad_ignore);
12072 tcase_add_test(tc_basic, test_entity_in_utf16_be_attr);
12073 tcase_add_test(tc_basic, test_entity_in_utf16_le_attr);
12074 tcase_add_test__ifdef_xml_dtd(tc_basic, test_entity_public_utf16_be);
12075 tcase_add_test__ifdef_xml_dtd(tc_basic, test_entity_public_utf16_le);
12076 tcase_add_test(tc_basic, test_short_doctype);
12077 tcase_add_test(tc_basic, test_short_doctype_2);
12078 tcase_add_test(tc_basic, test_short_doctype_3);
12079 tcase_add_test(tc_basic, test_long_doctype);
12080 tcase_add_test(tc_basic, test_bad_entity);
12081 tcase_add_test(tc_basic, test_bad_entity_2);
12082 tcase_add_test(tc_basic, test_bad_entity_3);
12083 tcase_add_test(tc_basic, test_bad_entity_4);
12084 tcase_add_test(tc_basic, test_bad_notation);
12085 tcase_add_test(tc_basic, test_default_doctype_handler);
12086 tcase_add_test(tc_basic, test_empty_element_abort);
12087
12088 suite_add_tcase(s, tc_namespace);
12089 tcase_add_checked_fixture(tc_namespace, namespace_setup, namespace_teardown);
12090 tcase_add_test(tc_namespace, test_return_ns_triplet);
12091 tcase_add_test(tc_namespace, test_ns_tagname_overwrite);
12092 tcase_add_test(tc_namespace, test_ns_tagname_overwrite_triplet);
12093 tcase_add_test(tc_namespace, test_start_ns_clears_start_element);
12094 tcase_add_test__ifdef_xml_dtd(tc_namespace,
12095 test_default_ns_from_ext_subset_and_ext_ge);
12096 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_1);
12097 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_2);
12098 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_3);
12099 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_4);
12100 tcase_add_test(tc_namespace, test_ns_unbound_prefix);
12101 tcase_add_test(tc_namespace, test_ns_default_with_empty_uri);
12102 tcase_add_test(tc_namespace, test_ns_duplicate_attrs_diff_prefixes);
12103 tcase_add_test(tc_namespace, test_ns_duplicate_hashes);
12104 tcase_add_test(tc_namespace, test_ns_unbound_prefix_on_attribute);
12105 tcase_add_test(tc_namespace, test_ns_unbound_prefix_on_element);
12106 tcase_add_test(tc_namespace, test_ns_parser_reset);
12107 tcase_add_test(tc_namespace, test_ns_long_element);
12108 tcase_add_test(tc_namespace, test_ns_mixed_prefix_atts);
12109 tcase_add_test(tc_namespace, test_ns_extend_uri_buffer);
12110 tcase_add_test(tc_namespace, test_ns_reserved_attributes);
12111 tcase_add_test(tc_namespace, test_ns_reserved_attributes_2);
12112 tcase_add_test(tc_namespace, test_ns_extremely_long_prefix);
12113 tcase_add_test(tc_namespace, test_ns_unknown_encoding_success);
12114 tcase_add_test(tc_namespace, test_ns_double_colon);
12115 tcase_add_test(tc_namespace, test_ns_double_colon_element);
12116 tcase_add_test(tc_namespace, test_ns_bad_attr_leafname);
12117 tcase_add_test(tc_namespace, test_ns_bad_element_leafname);
12118 tcase_add_test(tc_namespace, test_ns_utf16_leafname);
12119 tcase_add_test(tc_namespace, test_ns_utf16_element_leafname);
12120 tcase_add_test(tc_namespace, test_ns_utf16_doctype);
12121 tcase_add_test(tc_namespace, test_ns_invalid_doctype);
12122 tcase_add_test(tc_namespace, test_ns_double_colon_doctype);
12123 tcase_add_test(tc_namespace, test_ns_separator_in_uri);
12124
12125 suite_add_tcase(s, tc_misc);
12126 tcase_add_checked_fixture(tc_misc, NULL, basic_teardown);
12127 tcase_add_test(tc_misc, test_misc_alloc_create_parser);
12128 tcase_add_test(tc_misc, test_misc_alloc_create_parser_with_encoding);
12129 tcase_add_test(tc_misc, test_misc_null_parser);
12130 tcase_add_test(tc_misc, test_misc_error_string);
12131 tcase_add_test(tc_misc, test_misc_version);
12132 tcase_add_test(tc_misc, test_misc_features);
12133 tcase_add_test(tc_misc, test_misc_attribute_leak);
12134 tcase_add_test(tc_misc, test_misc_utf16le);
12135 tcase_add_test(tc_misc, test_misc_stop_during_end_handler_issue_240_1);
12136 tcase_add_test(tc_misc, test_misc_stop_during_end_handler_issue_240_2);
12137 tcase_add_test__ifdef_xml_dtd(
12138 tc_misc, test_misc_deny_internal_entity_closing_doctype_issue_317);
12139
12140 suite_add_tcase(s, tc_alloc);
12141 tcase_add_checked_fixture(tc_alloc, alloc_setup, alloc_teardown);
12142 tcase_add_test(tc_alloc, test_alloc_parse_xdecl);
12143 tcase_add_test(tc_alloc, test_alloc_parse_xdecl_2);
12144 tcase_add_test(tc_alloc, test_alloc_parse_pi);
12145 tcase_add_test(tc_alloc, test_alloc_parse_pi_2);
12146 tcase_add_test(tc_alloc, test_alloc_parse_pi_3);
12147 tcase_add_test(tc_alloc, test_alloc_parse_comment);
12148 tcase_add_test(tc_alloc, test_alloc_parse_comment_2);
12149 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_create_external_parser);
12150 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_run_external_parser);
12151 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_dtd_copy_default_atts);
12152 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_external_entity);
12153 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_ext_entity_set_encoding);
12154 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_internal_entity);
12155 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_dtd_default_handling);
12156 tcase_add_test(tc_alloc, test_alloc_explicit_encoding);
12157 tcase_add_test(tc_alloc, test_alloc_set_base);
12158 tcase_add_test(tc_alloc, test_alloc_realloc_buffer);
12159 tcase_add_test(tc_alloc, test_alloc_ext_entity_realloc_buffer);
12160 tcase_add_test(tc_alloc, test_alloc_realloc_many_attributes);
12161 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_public_entity_value);
12162 tcase_add_test__ifdef_xml_dtd(tc_alloc,
12163 test_alloc_realloc_subst_public_entity_value);
12164 tcase_add_test(tc_alloc, test_alloc_parse_public_doctype);
12165 tcase_add_test(tc_alloc, test_alloc_parse_public_doctype_long_name);
12166 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_set_foreign_dtd);
12167 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_attribute_enum_value);
12168 tcase_add_test__ifdef_xml_dtd(tc_alloc,
12169 test_alloc_realloc_attribute_enum_value);
12170 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_implied_attribute);
12171 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_default_attribute);
12172 tcase_add_test(tc_alloc, test_alloc_notation);
12173 tcase_add_test(tc_alloc, test_alloc_public_notation);
12174 tcase_add_test(tc_alloc, test_alloc_system_notation);
12175 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_nested_groups);
12176 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_nested_groups);
12177 tcase_add_test(tc_alloc, test_alloc_large_group);
12178 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_group_choice);
12179 tcase_add_test(tc_alloc, test_alloc_pi_in_epilog);
12180 tcase_add_test(tc_alloc, test_alloc_comment_in_epilog);
12181 tcase_add_test__ifdef_xml_dtd(tc_alloc,
12182 test_alloc_realloc_long_attribute_value);
12183 tcase_add_test(tc_alloc, test_alloc_attribute_whitespace);
12184 tcase_add_test(tc_alloc, test_alloc_attribute_predefined_entity);
12185 tcase_add_test(tc_alloc, test_alloc_long_attr_default_with_char_ref);
12186 tcase_add_test(tc_alloc, test_alloc_long_attr_value);
12187 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_nested_entities);
12188 tcase_add_test__ifdef_xml_dtd(tc_alloc,
12189 test_alloc_realloc_param_entity_newline);
12190 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_ce_extends_pe);
12191 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_attributes);
12192 tcase_add_test(tc_alloc, test_alloc_long_doc_name);
12193 tcase_add_test(tc_alloc, test_alloc_long_base);
12194 tcase_add_test(tc_alloc, test_alloc_long_public_id);
12195 tcase_add_test(tc_alloc, test_alloc_long_entity_value);
12196 tcase_add_test(tc_alloc, test_alloc_long_notation);
12197
12198 suite_add_tcase(s, tc_nsalloc);
12199 tcase_add_checked_fixture(tc_nsalloc, nsalloc_setup, nsalloc_teardown);
12200 tcase_add_test(tc_nsalloc, test_nsalloc_xmlns);
12201 tcase_add_test(tc_nsalloc, test_nsalloc_parse_buffer);
12202 tcase_add_test(tc_nsalloc, test_nsalloc_long_prefix);
12203 tcase_add_test(tc_nsalloc, test_nsalloc_long_uri);
12204 tcase_add_test(tc_nsalloc, test_nsalloc_long_attr);
12205 tcase_add_test(tc_nsalloc, test_nsalloc_long_attr_prefix);
12206 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_attributes);
12207 tcase_add_test(tc_nsalloc, test_nsalloc_long_element);
12208 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_binding_uri);
12209 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_prefix);
12210 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_longer_prefix);
12211 tcase_add_test(tc_nsalloc, test_nsalloc_long_namespace);
12212 tcase_add_test(tc_nsalloc, test_nsalloc_less_long_namespace);
12213 tcase_add_test(tc_nsalloc, test_nsalloc_long_context);
12214 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context);
12215 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_2);
12216 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_3);
12217 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_4);
12218 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_5);
12219 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_6);
12220 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_7);
12221 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_ge_name);
12222 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_in_dtd);
12223 tcase_add_test(tc_nsalloc, test_nsalloc_long_default_in_ext);
12224 tcase_add_test(tc_nsalloc, test_nsalloc_long_systemid_in_ext);
12225 tcase_add_test(tc_nsalloc, test_nsalloc_prefixed_element);
12226
12227 #if defined(XML_DTD)
12228 suite_add_tcase(s, tc_accounting);
12229 tcase_add_test(tc_accounting, test_accounting_precision);
12230 tcase_add_test(tc_accounting, test_billion_laughs_attack_protection_api);
12231 tcase_add_test(tc_accounting, test_helper_unsigned_char_to_printable);
12232 #endif
12233
12234 return s;
12235 }
12236
12237 int
main(int argc,char * argv[])12238 main(int argc, char *argv[]) {
12239 int i, nf;
12240 int verbosity = CK_NORMAL;
12241 Suite *s = make_suite();
12242 SRunner *sr = srunner_create(s);
12243
12244 /* run the tests for internal helper functions */
12245 testhelper_is_whitespace_normalized();
12246
12247 for (i = 1; i < argc; ++i) {
12248 char *opt = argv[i];
12249 if (strcmp(opt, "-v") == 0 || strcmp(opt, "--verbose") == 0)
12250 verbosity = CK_VERBOSE;
12251 else if (strcmp(opt, "-q") == 0 || strcmp(opt, "--quiet") == 0)
12252 verbosity = CK_SILENT;
12253 else {
12254 fprintf(stderr, "runtests: unknown option '%s'\n", opt);
12255 return 2;
12256 }
12257 }
12258 if (verbosity != CK_SILENT)
12259 printf("Expat version: %" XML_FMT_STR "\n", XML_ExpatVersion());
12260 srunner_run_all(sr, verbosity);
12261 nf = srunner_ntests_failed(sr);
12262 srunner_free(sr);
12263
12264 return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
12265 }
12266