1 /* Run the Expat test suite
2 __ __ _
3 ___\ \/ /_ __ __ _| |_
4 / _ \\ /| '_ \ / _` | __|
5 | __// \| |_) | (_| | |_
6 \___/_/\_\ .__/ \__,_|\__|
7 |_| XML parser
8
9 Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
10 Copyright (c) 2000-2017 Expat development team
11 Licensed under the MIT license:
12
13 Permission is hereby granted, free of charge, to any person obtaining
14 a copy of this software and associated documentation files (the
15 "Software"), to deal in the Software without restriction, including
16 without limitation the rights to use, copy, modify, merge, publish,
17 distribute, sublicense, and/or sell copies of the Software, and to permit
18 persons to whom the Software is furnished to do so, subject to the
19 following conditions:
20
21 The above copyright notice and this permission notice shall be included
22 in all copies or substantial portions of the Software.
23
24 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
27 NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
28 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
29 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
30 USE OR OTHER DEALINGS IN THE SOFTWARE.
31 */
32
33 #if defined(NDEBUG)
34 # undef NDEBUG /* because test suite relies on assert(...) at the moment */
35 #endif
36
37 #ifdef HAVE_EXPAT_CONFIG_H
38 # include <expat_config.h>
39 #endif
40
41 #include <assert.h>
42 #include <stdlib.h>
43 #include <stdio.h>
44 #include <string.h>
45 #include <stddef.h> /* ptrdiff_t */
46 #include <ctype.h>
47 #include <limits.h>
48
49 #if defined(_WIN32) && defined(_MSC_VER) && (_MSC_VER < 1600)
50 /* For vs2003/7.1 up to vs2008/9.0; _MSC_VER 1600 is vs2010/10.0 */
51 # if defined(_WIN64)
52 typedef __int64 intptr_t;
53 # else
54 typedef __int32 intptr_t;
55 # endif
56 typedef unsigned __int64 uint64_t;
57 #else
58 # include <stdint.h> /* intptr_t uint64_t */
59 #endif
60
61 #if ! defined(__cplusplus)
62 # if defined(_MSC_VER) && (_MSC_VER <= 1700)
63 /* for vs2012/11.0/1700 and earlier Visual Studio compilers */
64 # define bool int
65 # define false 0
66 # define true 1
67 # else
68 # include <stdbool.h>
69 # endif
70 #endif
71
72 #include "expat.h"
73 #include "chardata.h"
74 #include "structdata.h"
75 #include "internal.h" /* for UNUSED_P only */
76 #include "minicheck.h"
77 #include "memcheck.h"
78 #include "siphash.h"
79 #include "ascii.h" /* for ASCII_xxx */
80
81 #ifdef XML_LARGE_SIZE
82 # define XML_FMT_INT_MOD "ll"
83 #else
84 # define XML_FMT_INT_MOD "l"
85 #endif
86
87 #ifdef XML_UNICODE_WCHAR_T
88 # define XML_FMT_CHAR "lc"
89 # define XML_FMT_STR "ls"
90 # include <wchar.h>
91 # define xcstrlen(s) wcslen(s)
92 # define xcstrcmp(s, t) wcscmp((s), (t))
93 # define xcstrncmp(s, t, n) wcsncmp((s), (t), (n))
94 # define XCS(s) _XCS(s)
95 # define _XCS(s) L##s
96 #else
97 # ifdef XML_UNICODE
98 # error "No support for UTF-16 character without wchar_t in tests"
99 # else
100 # define XML_FMT_CHAR "c"
101 # define XML_FMT_STR "s"
102 # define xcstrlen(s) strlen(s)
103 # define xcstrcmp(s, t) strcmp((s), (t))
104 # define xcstrncmp(s, t, n) strncmp((s), (t), (n))
105 # define XCS(s) s
106 # endif /* XML_UNICODE */
107 #endif /* XML_UNICODE_WCHAR_T */
108
109 static XML_Parser g_parser = NULL;
110
111 static void
basic_setup(void)112 basic_setup(void) {
113 g_parser = XML_ParserCreate(NULL);
114 if (g_parser == NULL)
115 fail("Parser not created.");
116 }
117
118 static void
basic_teardown(void)119 basic_teardown(void) {
120 if (g_parser != NULL) {
121 XML_ParserFree(g_parser);
122 g_parser = NULL;
123 }
124 }
125
126 /* Generate a failure using the parser state to create an error message;
127 this should be used when the parser reports an error we weren't
128 expecting.
129 */
130 static void
_xml_failure(XML_Parser parser,const char * file,int line)131 _xml_failure(XML_Parser parser, const char *file, int line) {
132 char buffer[1024];
133 enum XML_Error err = XML_GetErrorCode(parser);
134 sprintf(buffer,
135 " %d: %" XML_FMT_STR " (line %" XML_FMT_INT_MOD
136 "u, offset %" XML_FMT_INT_MOD "u)\n reported from %s, line %d\n",
137 err, XML_ErrorString(err), XML_GetCurrentLineNumber(parser),
138 XML_GetCurrentColumnNumber(parser), file, line);
139 _fail_unless(0, file, line, buffer);
140 }
141
142 static enum XML_Status
_XML_Parse_SINGLE_BYTES(XML_Parser parser,const char * s,int len,int isFinal)143 _XML_Parse_SINGLE_BYTES(XML_Parser parser, const char *s, int len,
144 int isFinal) {
145 enum XML_Status res = XML_STATUS_ERROR;
146 int offset = 0;
147
148 if (len == 0) {
149 return XML_Parse(parser, s, len, isFinal);
150 }
151
152 for (; offset < len; offset++) {
153 const int innerIsFinal = (offset == len - 1) && isFinal;
154 const char c = s[offset]; /* to help out-of-bounds detection */
155 res = XML_Parse(parser, &c, sizeof(char), innerIsFinal);
156 if (res != XML_STATUS_OK) {
157 return res;
158 }
159 }
160 return res;
161 }
162
163 #define xml_failure(parser) _xml_failure((parser), __FILE__, __LINE__)
164
165 static void
_expect_failure(const char * text,enum XML_Error errorCode,const char * errorMessage,const char * file,int lineno)166 _expect_failure(const char *text, enum XML_Error errorCode,
167 const char *errorMessage, const char *file, int lineno) {
168 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
169 == XML_STATUS_OK)
170 /* Hackish use of _fail_unless() macro, but let's us report
171 the right filename and line number. */
172 _fail_unless(0, file, lineno, errorMessage);
173 if (XML_GetErrorCode(g_parser) != errorCode)
174 _xml_failure(g_parser, file, lineno);
175 }
176
177 #define expect_failure(text, errorCode, errorMessage) \
178 _expect_failure((text), (errorCode), (errorMessage), __FILE__, __LINE__)
179
180 /* Dummy handlers for when we need to set a handler to tickle a bug,
181 but it doesn't need to do anything.
182 */
183 static unsigned long dummy_handler_flags = 0;
184
185 #define DUMMY_START_DOCTYPE_HANDLER_FLAG (1UL << 0)
186 #define DUMMY_END_DOCTYPE_HANDLER_FLAG (1UL << 1)
187 #define DUMMY_ENTITY_DECL_HANDLER_FLAG (1UL << 2)
188 #define DUMMY_NOTATION_DECL_HANDLER_FLAG (1UL << 3)
189 #define DUMMY_ELEMENT_DECL_HANDLER_FLAG (1UL << 4)
190 #define DUMMY_ATTLIST_DECL_HANDLER_FLAG (1UL << 5)
191 #define DUMMY_COMMENT_HANDLER_FLAG (1UL << 6)
192 #define DUMMY_PI_HANDLER_FLAG (1UL << 7)
193 #define DUMMY_START_ELEMENT_HANDLER_FLAG (1UL << 8)
194 #define DUMMY_START_CDATA_HANDLER_FLAG (1UL << 9)
195 #define DUMMY_END_CDATA_HANDLER_FLAG (1UL << 10)
196 #define DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG (1UL << 11)
197 #define DUMMY_START_NS_DECL_HANDLER_FLAG (1UL << 12)
198 #define DUMMY_END_NS_DECL_HANDLER_FLAG (1UL << 13)
199 #define DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG (1UL << 14)
200 #define DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG (1UL << 15)
201 #define DUMMY_SKIP_HANDLER_FLAG (1UL << 16)
202 #define DUMMY_DEFAULT_HANDLER_FLAG (1UL << 17)
203
204 static void XMLCALL
dummy_xdecl_handler(void * userData,const XML_Char * version,const XML_Char * encoding,int standalone)205 dummy_xdecl_handler(void *userData, const XML_Char *version,
206 const XML_Char *encoding, int standalone) {
207 UNUSED_P(userData);
208 UNUSED_P(version);
209 UNUSED_P(encoding);
210 UNUSED_P(standalone);
211 }
212
213 static void XMLCALL
dummy_start_doctype_handler(void * userData,const XML_Char * doctypeName,const XML_Char * sysid,const XML_Char * pubid,int has_internal_subset)214 dummy_start_doctype_handler(void *userData, const XML_Char *doctypeName,
215 const XML_Char *sysid, const XML_Char *pubid,
216 int has_internal_subset) {
217 UNUSED_P(userData);
218 UNUSED_P(doctypeName);
219 UNUSED_P(sysid);
220 UNUSED_P(pubid);
221 UNUSED_P(has_internal_subset);
222 dummy_handler_flags |= DUMMY_START_DOCTYPE_HANDLER_FLAG;
223 }
224
225 static void XMLCALL
dummy_end_doctype_handler(void * userData)226 dummy_end_doctype_handler(void *userData) {
227 UNUSED_P(userData);
228 dummy_handler_flags |= DUMMY_END_DOCTYPE_HANDLER_FLAG;
229 }
230
231 static void XMLCALL
dummy_entity_decl_handler(void * userData,const XML_Char * entityName,int is_parameter_entity,const XML_Char * value,int value_length,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId,const XML_Char * notationName)232 dummy_entity_decl_handler(void *userData, const XML_Char *entityName,
233 int is_parameter_entity, const XML_Char *value,
234 int value_length, const XML_Char *base,
235 const XML_Char *systemId, const XML_Char *publicId,
236 const XML_Char *notationName) {
237 UNUSED_P(userData);
238 UNUSED_P(entityName);
239 UNUSED_P(is_parameter_entity);
240 UNUSED_P(value);
241 UNUSED_P(value_length);
242 UNUSED_P(base);
243 UNUSED_P(systemId);
244 UNUSED_P(publicId);
245 UNUSED_P(notationName);
246 dummy_handler_flags |= DUMMY_ENTITY_DECL_HANDLER_FLAG;
247 }
248
249 static void XMLCALL
dummy_notation_decl_handler(void * userData,const XML_Char * notationName,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)250 dummy_notation_decl_handler(void *userData, const XML_Char *notationName,
251 const XML_Char *base, const XML_Char *systemId,
252 const XML_Char *publicId) {
253 UNUSED_P(userData);
254 UNUSED_P(notationName);
255 UNUSED_P(base);
256 UNUSED_P(systemId);
257 UNUSED_P(publicId);
258 dummy_handler_flags |= DUMMY_NOTATION_DECL_HANDLER_FLAG;
259 }
260
261 static void XMLCALL
dummy_element_decl_handler(void * userData,const XML_Char * name,XML_Content * model)262 dummy_element_decl_handler(void *userData, const XML_Char *name,
263 XML_Content *model) {
264 UNUSED_P(userData);
265 UNUSED_P(name);
266 /* The content model must be freed by the handler. Unfortunately
267 * we cannot pass the parser as the userData because this is used
268 * with other handlers that require other userData.
269 */
270 XML_FreeContentModel(g_parser, model);
271 dummy_handler_flags |= DUMMY_ELEMENT_DECL_HANDLER_FLAG;
272 }
273
274 static void XMLCALL
dummy_attlist_decl_handler(void * userData,const XML_Char * elname,const XML_Char * attname,const XML_Char * att_type,const XML_Char * dflt,int isrequired)275 dummy_attlist_decl_handler(void *userData, const XML_Char *elname,
276 const XML_Char *attname, const XML_Char *att_type,
277 const XML_Char *dflt, int isrequired) {
278 UNUSED_P(userData);
279 UNUSED_P(elname);
280 UNUSED_P(attname);
281 UNUSED_P(att_type);
282 UNUSED_P(dflt);
283 UNUSED_P(isrequired);
284 dummy_handler_flags |= DUMMY_ATTLIST_DECL_HANDLER_FLAG;
285 }
286
287 static void XMLCALL
dummy_comment_handler(void * userData,const XML_Char * data)288 dummy_comment_handler(void *userData, const XML_Char *data) {
289 UNUSED_P(userData);
290 UNUSED_P(data);
291 dummy_handler_flags |= DUMMY_COMMENT_HANDLER_FLAG;
292 }
293
294 static void XMLCALL
dummy_pi_handler(void * userData,const XML_Char * target,const XML_Char * data)295 dummy_pi_handler(void *userData, const XML_Char *target, const XML_Char *data) {
296 UNUSED_P(userData);
297 UNUSED_P(target);
298 UNUSED_P(data);
299 dummy_handler_flags |= DUMMY_PI_HANDLER_FLAG;
300 }
301
302 static void XMLCALL
dummy_start_element(void * userData,const XML_Char * name,const XML_Char ** atts)303 dummy_start_element(void *userData, const XML_Char *name,
304 const XML_Char **atts) {
305 UNUSED_P(userData);
306 UNUSED_P(name);
307 UNUSED_P(atts);
308 dummy_handler_flags |= DUMMY_START_ELEMENT_HANDLER_FLAG;
309 }
310
311 static void XMLCALL
dummy_end_element(void * userData,const XML_Char * name)312 dummy_end_element(void *userData, const XML_Char *name) {
313 UNUSED_P(userData);
314 UNUSED_P(name);
315 }
316
317 static void XMLCALL
dummy_start_cdata_handler(void * userData)318 dummy_start_cdata_handler(void *userData) {
319 UNUSED_P(userData);
320 dummy_handler_flags |= DUMMY_START_CDATA_HANDLER_FLAG;
321 }
322
323 static void XMLCALL
dummy_end_cdata_handler(void * userData)324 dummy_end_cdata_handler(void *userData) {
325 UNUSED_P(userData);
326 dummy_handler_flags |= DUMMY_END_CDATA_HANDLER_FLAG;
327 }
328
329 static void XMLCALL
dummy_cdata_handler(void * userData,const XML_Char * s,int len)330 dummy_cdata_handler(void *userData, const XML_Char *s, int len) {
331 UNUSED_P(userData);
332 UNUSED_P(s);
333 UNUSED_P(len);
334 }
335
336 static void XMLCALL
dummy_start_namespace_decl_handler(void * userData,const XML_Char * prefix,const XML_Char * uri)337 dummy_start_namespace_decl_handler(void *userData, const XML_Char *prefix,
338 const XML_Char *uri) {
339 UNUSED_P(userData);
340 UNUSED_P(prefix);
341 UNUSED_P(uri);
342 dummy_handler_flags |= DUMMY_START_NS_DECL_HANDLER_FLAG;
343 }
344
345 static void XMLCALL
dummy_end_namespace_decl_handler(void * userData,const XML_Char * prefix)346 dummy_end_namespace_decl_handler(void *userData, const XML_Char *prefix) {
347 UNUSED_P(userData);
348 UNUSED_P(prefix);
349 dummy_handler_flags |= DUMMY_END_NS_DECL_HANDLER_FLAG;
350 }
351
352 /* This handler is obsolete, but while the code exists we should
353 * ensure that dealing with the handler is covered by tests.
354 */
355 static void XMLCALL
dummy_unparsed_entity_decl_handler(void * userData,const XML_Char * entityName,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId,const XML_Char * notationName)356 dummy_unparsed_entity_decl_handler(void *userData, const XML_Char *entityName,
357 const XML_Char *base,
358 const XML_Char *systemId,
359 const XML_Char *publicId,
360 const XML_Char *notationName) {
361 UNUSED_P(userData);
362 UNUSED_P(entityName);
363 UNUSED_P(base);
364 UNUSED_P(systemId);
365 UNUSED_P(publicId);
366 UNUSED_P(notationName);
367 dummy_handler_flags |= DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG;
368 }
369
370 static void XMLCALL
dummy_default_handler(void * userData,const XML_Char * s,int len)371 dummy_default_handler(void *userData, const XML_Char *s, int len) {
372 UNUSED_P(userData);
373 UNUSED_P(s);
374 UNUSED_P(len);
375 }
376
377 static void XMLCALL
dummy_start_doctype_decl_handler(void * userData,const XML_Char * doctypeName,const XML_Char * sysid,const XML_Char * pubid,int has_internal_subset)378 dummy_start_doctype_decl_handler(void *userData, const XML_Char *doctypeName,
379 const XML_Char *sysid, const XML_Char *pubid,
380 int has_internal_subset) {
381 UNUSED_P(userData);
382 UNUSED_P(doctypeName);
383 UNUSED_P(sysid);
384 UNUSED_P(pubid);
385 UNUSED_P(has_internal_subset);
386 dummy_handler_flags |= DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG;
387 }
388
389 static void XMLCALL
dummy_end_doctype_decl_handler(void * userData)390 dummy_end_doctype_decl_handler(void *userData) {
391 UNUSED_P(userData);
392 dummy_handler_flags |= DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG;
393 }
394
395 static void XMLCALL
dummy_skip_handler(void * userData,const XML_Char * entityName,int is_parameter_entity)396 dummy_skip_handler(void *userData, const XML_Char *entityName,
397 int is_parameter_entity) {
398 UNUSED_P(userData);
399 UNUSED_P(entityName);
400 UNUSED_P(is_parameter_entity);
401 dummy_handler_flags |= DUMMY_SKIP_HANDLER_FLAG;
402 }
403
404 /* Useful external entity handler */
405 typedef struct ExtOption {
406 const XML_Char *system_id;
407 const char *parse_text;
408 } ExtOption;
409
410 static int XMLCALL
external_entity_optioner(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)411 external_entity_optioner(XML_Parser parser, const XML_Char *context,
412 const XML_Char *base, const XML_Char *systemId,
413 const XML_Char *publicId) {
414 ExtOption *options = (ExtOption *)XML_GetUserData(parser);
415 XML_Parser ext_parser;
416
417 UNUSED_P(base);
418 UNUSED_P(publicId);
419 while (options->parse_text != NULL) {
420 if (! xcstrcmp(systemId, options->system_id)) {
421 enum XML_Status rc;
422 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
423 if (ext_parser == NULL)
424 return XML_STATUS_ERROR;
425 rc = _XML_Parse_SINGLE_BYTES(ext_parser, options->parse_text,
426 (int)strlen(options->parse_text), XML_TRUE);
427 XML_ParserFree(ext_parser);
428 return rc;
429 }
430 options++;
431 }
432 fail("No suitable option found");
433 return XML_STATUS_ERROR;
434 }
435
436 /*
437 * Parameter entity evaluation support.
438 */
439 #define ENTITY_MATCH_FAIL (-1)
440 #define ENTITY_MATCH_NOT_FOUND (0)
441 #define ENTITY_MATCH_SUCCESS (1)
442 static const XML_Char *entity_name_to_match = NULL;
443 static const XML_Char *entity_value_to_match = NULL;
444 static int entity_match_flag = ENTITY_MATCH_NOT_FOUND;
445
446 static void XMLCALL
param_entity_match_handler(void * userData,const XML_Char * entityName,int is_parameter_entity,const XML_Char * value,int value_length,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId,const XML_Char * notationName)447 param_entity_match_handler(void *userData, const XML_Char *entityName,
448 int is_parameter_entity, const XML_Char *value,
449 int value_length, const XML_Char *base,
450 const XML_Char *systemId, const XML_Char *publicId,
451 const XML_Char *notationName) {
452 UNUSED_P(userData);
453 UNUSED_P(base);
454 UNUSED_P(systemId);
455 UNUSED_P(publicId);
456 UNUSED_P(notationName);
457 if (! is_parameter_entity || entity_name_to_match == NULL
458 || entity_value_to_match == NULL) {
459 return;
460 }
461 if (! xcstrcmp(entityName, entity_name_to_match)) {
462 /* The cast here is safe because we control the horizontal and
463 * the vertical, and we therefore know our strings are never
464 * going to overflow an int.
465 */
466 if (value_length != (int)xcstrlen(entity_value_to_match)
467 || xcstrncmp(value, entity_value_to_match, value_length)) {
468 entity_match_flag = ENTITY_MATCH_FAIL;
469 } else {
470 entity_match_flag = ENTITY_MATCH_SUCCESS;
471 }
472 }
473 /* Else leave the match flag alone */
474 }
475
476 /*
477 * Character & encoding tests.
478 */
479
START_TEST(test_nul_byte)480 START_TEST(test_nul_byte) {
481 char text[] = "<doc>\0</doc>";
482
483 /* test that a NUL byte (in US-ASCII data) is an error */
484 if (_XML_Parse_SINGLE_BYTES(g_parser, text, sizeof(text) - 1, XML_TRUE)
485 == XML_STATUS_OK)
486 fail("Parser did not report error on NUL-byte.");
487 if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
488 xml_failure(g_parser);
489 }
490 END_TEST
491
START_TEST(test_u0000_char)492 START_TEST(test_u0000_char) {
493 /* test that a NUL byte (in US-ASCII data) is an error */
494 expect_failure("<doc>�</doc>", XML_ERROR_BAD_CHAR_REF,
495 "Parser did not report error on NUL-byte.");
496 }
497 END_TEST
498
START_TEST(test_siphash_self)499 START_TEST(test_siphash_self) {
500 if (! sip24_valid())
501 fail("SipHash self-test failed");
502 }
503 END_TEST
504
START_TEST(test_siphash_spec)505 START_TEST(test_siphash_spec) {
506 /* https://131002.net/siphash/siphash.pdf (page 19, "Test values") */
507 const char message[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09"
508 "\x0a\x0b\x0c\x0d\x0e";
509 const size_t len = sizeof(message) - 1;
510 const uint64_t expected = _SIP_ULL(0xa129ca61U, 0x49be45e5U);
511 struct siphash state;
512 struct sipkey key;
513
514 sip_tokey(&key, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09"
515 "\x0a\x0b\x0c\x0d\x0e\x0f");
516 sip24_init(&state, &key);
517
518 /* Cover spread across calls */
519 sip24_update(&state, message, 4);
520 sip24_update(&state, message + 4, len - 4);
521
522 /* Cover null length */
523 sip24_update(&state, message, 0);
524
525 if (sip24_final(&state) != expected)
526 fail("sip24_final failed spec test\n");
527
528 /* Cover wrapper */
529 if (siphash24(message, len, &key) != expected)
530 fail("siphash24 failed spec test\n");
531 }
532 END_TEST
533
START_TEST(test_bom_utf8)534 START_TEST(test_bom_utf8) {
535 /* This test is really just making sure we don't core on a UTF-8 BOM. */
536 const char *text = "\357\273\277<e/>";
537
538 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
539 == XML_STATUS_ERROR)
540 xml_failure(g_parser);
541 }
542 END_TEST
543
START_TEST(test_bom_utf16_be)544 START_TEST(test_bom_utf16_be) {
545 char text[] = "\376\377\0<\0e\0/\0>";
546
547 if (_XML_Parse_SINGLE_BYTES(g_parser, text, sizeof(text) - 1, XML_TRUE)
548 == XML_STATUS_ERROR)
549 xml_failure(g_parser);
550 }
551 END_TEST
552
START_TEST(test_bom_utf16_le)553 START_TEST(test_bom_utf16_le) {
554 char text[] = "\377\376<\0e\0/\0>\0";
555
556 if (_XML_Parse_SINGLE_BYTES(g_parser, text, sizeof(text) - 1, XML_TRUE)
557 == XML_STATUS_ERROR)
558 xml_failure(g_parser);
559 }
560 END_TEST
561
562 /* Parse whole buffer at once to exercise a different code path */
START_TEST(test_nobom_utf16_le)563 START_TEST(test_nobom_utf16_le) {
564 char text[] = " \0<\0e\0/\0>\0";
565
566 if (XML_Parse(g_parser, text, sizeof(text) - 1, XML_TRUE) == XML_STATUS_ERROR)
567 xml_failure(g_parser);
568 }
569 END_TEST
570
571 static void XMLCALL
accumulate_characters(void * userData,const XML_Char * s,int len)572 accumulate_characters(void *userData, const XML_Char *s, int len) {
573 CharData_AppendXMLChars((CharData *)userData, s, len);
574 }
575
576 static void XMLCALL
accumulate_attribute(void * userData,const XML_Char * name,const XML_Char ** atts)577 accumulate_attribute(void *userData, const XML_Char *name,
578 const XML_Char **atts) {
579 CharData *storage = (CharData *)userData;
580 UNUSED_P(name);
581 /* Check there are attributes to deal with */
582 if (atts == NULL)
583 return;
584
585 while (storage->count < 0 && atts[0] != NULL) {
586 /* "accumulate" the value of the first attribute we see */
587 CharData_AppendXMLChars(storage, atts[1], -1);
588 atts += 2;
589 }
590 }
591
592 static void
_run_character_check(const char * text,const XML_Char * expected,const char * file,int line)593 _run_character_check(const char *text, const XML_Char *expected,
594 const char *file, int line) {
595 CharData storage;
596
597 CharData_Init(&storage);
598 XML_SetUserData(g_parser, &storage);
599 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
600 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
601 == XML_STATUS_ERROR)
602 _xml_failure(g_parser, file, line);
603 CharData_CheckXMLChars(&storage, expected);
604 }
605
606 #define run_character_check(text, expected) \
607 _run_character_check(text, expected, __FILE__, __LINE__)
608
609 static void
_run_attribute_check(const char * text,const XML_Char * expected,const char * file,int line)610 _run_attribute_check(const char *text, const XML_Char *expected,
611 const char *file, int line) {
612 CharData storage;
613
614 CharData_Init(&storage);
615 XML_SetUserData(g_parser, &storage);
616 XML_SetStartElementHandler(g_parser, accumulate_attribute);
617 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
618 == XML_STATUS_ERROR)
619 _xml_failure(g_parser, file, line);
620 CharData_CheckXMLChars(&storage, expected);
621 }
622
623 #define run_attribute_check(text, expected) \
624 _run_attribute_check(text, expected, __FILE__, __LINE__)
625
626 typedef struct ExtTest {
627 const char *parse_text;
628 const XML_Char *encoding;
629 CharData *storage;
630 } ExtTest;
631
632 static void XMLCALL
ext_accumulate_characters(void * userData,const XML_Char * s,int len)633 ext_accumulate_characters(void *userData, const XML_Char *s, int len) {
634 ExtTest *test_data = (ExtTest *)userData;
635 accumulate_characters(test_data->storage, s, len);
636 }
637
638 static void
_run_ext_character_check(const char * text,ExtTest * test_data,const XML_Char * expected,const char * file,int line)639 _run_ext_character_check(const char *text, ExtTest *test_data,
640 const XML_Char *expected, const char *file, int line) {
641 CharData *const storage = (CharData *)malloc(sizeof(CharData));
642
643 CharData_Init(storage);
644 test_data->storage = storage;
645 XML_SetUserData(g_parser, test_data);
646 XML_SetCharacterDataHandler(g_parser, ext_accumulate_characters);
647 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
648 == XML_STATUS_ERROR)
649 _xml_failure(g_parser, file, line);
650 CharData_CheckXMLChars(storage, expected);
651
652 free(storage);
653 }
654
655 #define run_ext_character_check(text, test_data, expected) \
656 _run_ext_character_check(text, test_data, expected, __FILE__, __LINE__)
657
658 /* Regression test for SF bug #491986. */
START_TEST(test_danish_latin1)659 START_TEST(test_danish_latin1) {
660 const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
661 "<e>J\xF8rgen \xE6\xF8\xE5\xC6\xD8\xC5</e>";
662 #ifdef XML_UNICODE
663 const XML_Char *expected
664 = XCS("J\x00f8rgen \x00e6\x00f8\x00e5\x00c6\x00d8\x00c5");
665 #else
666 const XML_Char *expected
667 = XCS("J\xC3\xB8rgen \xC3\xA6\xC3\xB8\xC3\xA5\xC3\x86\xC3\x98\xC3\x85");
668 #endif
669 run_character_check(text, expected);
670 }
671 END_TEST
672
673 /* Regression test for SF bug #514281. */
START_TEST(test_french_charref_hexidecimal)674 START_TEST(test_french_charref_hexidecimal) {
675 const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
676 "<doc>éèàçêÈ</doc>";
677 #ifdef XML_UNICODE
678 const XML_Char *expected = XCS("\x00e9\x00e8\x00e0\x00e7\x00ea\x00c8");
679 #else
680 const XML_Char *expected
681 = XCS("\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88");
682 #endif
683 run_character_check(text, expected);
684 }
685 END_TEST
686
START_TEST(test_french_charref_decimal)687 START_TEST(test_french_charref_decimal) {
688 const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
689 "<doc>éèàçêÈ</doc>";
690 #ifdef XML_UNICODE
691 const XML_Char *expected = XCS("\x00e9\x00e8\x00e0\x00e7\x00ea\x00c8");
692 #else
693 const XML_Char *expected
694 = XCS("\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88");
695 #endif
696 run_character_check(text, expected);
697 }
698 END_TEST
699
START_TEST(test_french_latin1)700 START_TEST(test_french_latin1) {
701 const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
702 "<doc>\xE9\xE8\xE0\xE7\xEa\xC8</doc>";
703 #ifdef XML_UNICODE
704 const XML_Char *expected = XCS("\x00e9\x00e8\x00e0\x00e7\x00ea\x00c8");
705 #else
706 const XML_Char *expected
707 = XCS("\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88");
708 #endif
709 run_character_check(text, expected);
710 }
711 END_TEST
712
START_TEST(test_french_utf8)713 START_TEST(test_french_utf8) {
714 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
715 "<doc>\xC3\xA9</doc>";
716 #ifdef XML_UNICODE
717 const XML_Char *expected = XCS("\x00e9");
718 #else
719 const XML_Char *expected = XCS("\xC3\xA9");
720 #endif
721 run_character_check(text, expected);
722 }
723 END_TEST
724
725 /* Regression test for SF bug #600479.
726 XXX There should be a test that exercises all legal XML Unicode
727 characters as PCDATA and attribute value content, and XML Name
728 characters as part of element and attribute names.
729 */
START_TEST(test_utf8_false_rejection)730 START_TEST(test_utf8_false_rejection) {
731 const char *text = "<doc>\xEF\xBA\xBF</doc>";
732 #ifdef XML_UNICODE
733 const XML_Char *expected = XCS("\xfebf");
734 #else
735 const XML_Char *expected = XCS("\xEF\xBA\xBF");
736 #endif
737 run_character_check(text, expected);
738 }
739 END_TEST
740
741 /* Regression test for SF bug #477667.
742 This test assures that any 8-bit character followed by a 7-bit
743 character will not be mistakenly interpreted as a valid UTF-8
744 sequence.
745 */
START_TEST(test_illegal_utf8)746 START_TEST(test_illegal_utf8) {
747 char text[100];
748 int i;
749
750 for (i = 128; i <= 255; ++i) {
751 sprintf(text, "<e>%ccd</e>", i);
752 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
753 == XML_STATUS_OK) {
754 sprintf(text, "expected token error for '%c' (ordinal %d) in UTF-8 text",
755 i, i);
756 fail(text);
757 } else if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
758 xml_failure(g_parser);
759 /* Reset the parser since we use the same parser repeatedly. */
760 XML_ParserReset(g_parser, NULL);
761 }
762 }
763 END_TEST
764
765 /* Examples, not masks: */
766 #define UTF8_LEAD_1 "\x7f" /* 0b01111111 */
767 #define UTF8_LEAD_2 "\xdf" /* 0b11011111 */
768 #define UTF8_LEAD_3 "\xef" /* 0b11101111 */
769 #define UTF8_LEAD_4 "\xf7" /* 0b11110111 */
770 #define UTF8_FOLLOW "\xbf" /* 0b10111111 */
771
START_TEST(test_utf8_auto_align)772 START_TEST(test_utf8_auto_align) {
773 struct TestCase {
774 ptrdiff_t expectedMovementInChars;
775 const char *input;
776 };
777
778 struct TestCase cases[] = {
779 {00, ""},
780
781 {00, UTF8_LEAD_1},
782
783 {-1, UTF8_LEAD_2},
784 {00, UTF8_LEAD_2 UTF8_FOLLOW},
785
786 {-1, UTF8_LEAD_3},
787 {-2, UTF8_LEAD_3 UTF8_FOLLOW},
788 {00, UTF8_LEAD_3 UTF8_FOLLOW UTF8_FOLLOW},
789
790 {-1, UTF8_LEAD_4},
791 {-2, UTF8_LEAD_4 UTF8_FOLLOW},
792 {-3, UTF8_LEAD_4 UTF8_FOLLOW UTF8_FOLLOW},
793 {00, UTF8_LEAD_4 UTF8_FOLLOW UTF8_FOLLOW UTF8_FOLLOW},
794 };
795
796 size_t i = 0;
797 bool success = true;
798 for (; i < sizeof(cases) / sizeof(*cases); i++) {
799 const char *fromLim = cases[i].input + strlen(cases[i].input);
800 const char *const fromLimInitially = fromLim;
801 ptrdiff_t actualMovementInChars;
802
803 _INTERNAL_trim_to_complete_utf8_characters(cases[i].input, &fromLim);
804
805 actualMovementInChars = (fromLim - fromLimInitially);
806 if (actualMovementInChars != cases[i].expectedMovementInChars) {
807 size_t j = 0;
808 success = false;
809 printf("[-] UTF-8 case %2u: Expected movement by %2d chars"
810 ", actually moved by %2d chars: \"",
811 (unsigned)(i + 1), (int)cases[i].expectedMovementInChars,
812 (int)actualMovementInChars);
813 for (; j < strlen(cases[i].input); j++) {
814 printf("\\x%02x", (unsigned char)cases[i].input[j]);
815 }
816 printf("\"\n");
817 }
818 }
819
820 if (! success) {
821 fail("UTF-8 auto-alignment is not bullet-proof\n");
822 }
823 }
824 END_TEST
825
START_TEST(test_utf16)826 START_TEST(test_utf16) {
827 /* <?xml version="1.0" encoding="UTF-16"?>
828 * <doc a='123'>some {A} text</doc>
829 *
830 * where {A} is U+FF21, FULLWIDTH LATIN CAPITAL LETTER A
831 */
832 char text[]
833 = "\000<\000?\000x\000m\000\154\000 \000v\000e\000r\000s\000i\000o"
834 "\000n\000=\000'\0001\000.\000\060\000'\000 \000e\000n\000c\000o"
835 "\000d\000i\000n\000g\000=\000'\000U\000T\000F\000-\0001\000\066"
836 "\000'\000?\000>\000\n"
837 "\000<\000d\000o\000c\000 \000a\000=\000'\0001\0002\0003\000'\000>"
838 "\000s\000o\000m\000e\000 \xff\x21\000 \000t\000e\000x\000t\000"
839 "<\000/\000d\000o\000c\000>";
840 #ifdef XML_UNICODE
841 const XML_Char *expected = XCS("some \xff21 text");
842 #else
843 const XML_Char *expected = XCS("some \357\274\241 text");
844 #endif
845 CharData storage;
846
847 CharData_Init(&storage);
848 XML_SetUserData(g_parser, &storage);
849 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
850 if (_XML_Parse_SINGLE_BYTES(g_parser, text, sizeof(text) - 1, XML_TRUE)
851 == XML_STATUS_ERROR)
852 xml_failure(g_parser);
853 CharData_CheckXMLChars(&storage, expected);
854 }
855 END_TEST
856
START_TEST(test_utf16_le_epilog_newline)857 START_TEST(test_utf16_le_epilog_newline) {
858 unsigned int first_chunk_bytes = 17;
859 char text[] = "\xFF\xFE" /* BOM */
860 "<\000e\000/\000>\000" /* document element */
861 "\r\000\n\000\r\000\n\000"; /* epilog */
862
863 if (first_chunk_bytes >= sizeof(text) - 1)
864 fail("bad value of first_chunk_bytes");
865 if (_XML_Parse_SINGLE_BYTES(g_parser, text, first_chunk_bytes, XML_FALSE)
866 == XML_STATUS_ERROR)
867 xml_failure(g_parser);
868 else {
869 enum XML_Status rc;
870 rc = _XML_Parse_SINGLE_BYTES(g_parser, text + first_chunk_bytes,
871 sizeof(text) - first_chunk_bytes - 1,
872 XML_TRUE);
873 if (rc == XML_STATUS_ERROR)
874 xml_failure(g_parser);
875 }
876 }
877 END_TEST
878
879 /* Test that an outright lie in the encoding is faulted */
START_TEST(test_not_utf16)880 START_TEST(test_not_utf16) {
881 const char *text = "<?xml version='1.0' encoding='utf-16'?>"
882 "<doc>Hi</doc>";
883
884 /* Use a handler to provoke the appropriate code paths */
885 XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler);
886 expect_failure(text, XML_ERROR_INCORRECT_ENCODING,
887 "UTF-16 declared in UTF-8 not faulted");
888 }
889 END_TEST
890
891 /* Test that an unknown encoding is rejected */
START_TEST(test_bad_encoding)892 START_TEST(test_bad_encoding) {
893 const char *text = "<doc>Hi</doc>";
894
895 if (! XML_SetEncoding(g_parser, XCS("unknown-encoding")))
896 fail("XML_SetEncoding failed");
897 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
898 "Unknown encoding not faulted");
899 }
900 END_TEST
901
902 /* Regression test for SF bug #481609, #774028. */
START_TEST(test_latin1_umlauts)903 START_TEST(test_latin1_umlauts) {
904 const char *text
905 = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
906 "<e a='\xE4 \xF6 \xFC ä ö ü ä ö ü >'\n"
907 " >\xE4 \xF6 \xFC ä ö ü ä ö ü ></e>";
908 #ifdef XML_UNICODE
909 /* Expected results in UTF-16 */
910 const XML_Char *expected = XCS("\x00e4 \x00f6 \x00fc ")
911 XCS("\x00e4 \x00f6 \x00fc ") XCS("\x00e4 \x00f6 \x00fc >");
912 #else
913 /* Expected results in UTF-8 */
914 const XML_Char *expected = XCS("\xC3\xA4 \xC3\xB6 \xC3\xBC ")
915 XCS("\xC3\xA4 \xC3\xB6 \xC3\xBC ") XCS("\xC3\xA4 \xC3\xB6 \xC3\xBC >");
916 #endif
917
918 run_character_check(text, expected);
919 XML_ParserReset(g_parser, NULL);
920 run_attribute_check(text, expected);
921 /* Repeat with a default handler */
922 XML_ParserReset(g_parser, NULL);
923 XML_SetDefaultHandler(g_parser, dummy_default_handler);
924 run_character_check(text, expected);
925 XML_ParserReset(g_parser, NULL);
926 XML_SetDefaultHandler(g_parser, dummy_default_handler);
927 run_attribute_check(text, expected);
928 }
929 END_TEST
930
931 /* Test that an element name with a 4-byte UTF-8 character is rejected */
START_TEST(test_long_utf8_character)932 START_TEST(test_long_utf8_character) {
933 const char *text
934 = "<?xml version='1.0' encoding='utf-8'?>\n"
935 /* 0xf0 0x90 0x80 0x80 = U+10000, the first Linear B character */
936 "<do\xf0\x90\x80\x80/>";
937 expect_failure(text, XML_ERROR_INVALID_TOKEN,
938 "4-byte UTF-8 character in element name not faulted");
939 }
940 END_TEST
941
942 /* Test that a long latin-1 attribute (too long to convert in one go)
943 * is correctly converted
944 */
START_TEST(test_long_latin1_attribute)945 START_TEST(test_long_latin1_attribute) {
946 const char *text
947 = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
948 "<doc att='"
949 /* 64 characters per line */
950 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
951 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
952 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
953 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
954 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
955 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
956 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
957 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
958 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
959 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
960 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
961 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
962 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
963 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
964 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
965 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
966 /* Last character splits across a buffer boundary */
967 "\xe4'>\n</doc>";
968
969 const XML_Char *expected =
970 /* 64 characters per line */
971 /* clang-format off */
972 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
973 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
974 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
975 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
976 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
977 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
978 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
979 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
980 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
981 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
982 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
983 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
984 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
985 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
986 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
987 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO")
988 /* clang-format on */
989 #ifdef XML_UNICODE
990 XCS("\x00e4");
991 #else
992 XCS("\xc3\xa4");
993 #endif
994
995 run_attribute_check(text, expected);
996 }
997 END_TEST
998
999 /* Test that a long ASCII attribute (too long to convert in one go)
1000 * is correctly converted
1001 */
START_TEST(test_long_ascii_attribute)1002 START_TEST(test_long_ascii_attribute) {
1003 const char *text
1004 = "<?xml version='1.0' encoding='us-ascii'?>\n"
1005 "<doc att='"
1006 /* 64 characters per line */
1007 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1008 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1009 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1010 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1011 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1012 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1013 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1014 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1015 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1016 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1017 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1018 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1019 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1020 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1021 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1022 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1023 "01234'>\n</doc>";
1024 const XML_Char *expected =
1025 /* 64 characters per line */
1026 /* clang-format off */
1027 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1028 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1029 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1030 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1031 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1032 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1033 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1034 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1035 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1036 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1037 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1038 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1039 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1040 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1041 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1042 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1043 XCS("01234");
1044 /* clang-format on */
1045
1046 run_attribute_check(text, expected);
1047 }
1048 END_TEST
1049
1050 /* Regression test #1 for SF bug #653180. */
START_TEST(test_line_number_after_parse)1051 START_TEST(test_line_number_after_parse) {
1052 const char *text = "<tag>\n"
1053 "\n"
1054 "\n</tag>";
1055 XML_Size lineno;
1056
1057 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
1058 == XML_STATUS_ERROR)
1059 xml_failure(g_parser);
1060 lineno = XML_GetCurrentLineNumber(g_parser);
1061 if (lineno != 4) {
1062 char buffer[100];
1063 sprintf(buffer, "expected 4 lines, saw %" XML_FMT_INT_MOD "u", lineno);
1064 fail(buffer);
1065 }
1066 }
1067 END_TEST
1068
1069 /* Regression test #2 for SF bug #653180. */
START_TEST(test_column_number_after_parse)1070 START_TEST(test_column_number_after_parse) {
1071 const char *text = "<tag></tag>";
1072 XML_Size colno;
1073
1074 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
1075 == XML_STATUS_ERROR)
1076 xml_failure(g_parser);
1077 colno = XML_GetCurrentColumnNumber(g_parser);
1078 if (colno != 11) {
1079 char buffer[100];
1080 sprintf(buffer, "expected 11 columns, saw %" XML_FMT_INT_MOD "u", colno);
1081 fail(buffer);
1082 }
1083 }
1084 END_TEST
1085
1086 #define STRUCT_START_TAG 0
1087 #define STRUCT_END_TAG 1
1088 static void XMLCALL
start_element_event_handler2(void * userData,const XML_Char * name,const XML_Char ** attr)1089 start_element_event_handler2(void *userData, const XML_Char *name,
1090 const XML_Char **attr) {
1091 StructData *storage = (StructData *)userData;
1092 UNUSED_P(attr);
1093 StructData_AddItem(storage, name, XML_GetCurrentColumnNumber(g_parser),
1094 XML_GetCurrentLineNumber(g_parser), STRUCT_START_TAG);
1095 }
1096
1097 static void XMLCALL
end_element_event_handler2(void * userData,const XML_Char * name)1098 end_element_event_handler2(void *userData, const XML_Char *name) {
1099 StructData *storage = (StructData *)userData;
1100 StructData_AddItem(storage, name, XML_GetCurrentColumnNumber(g_parser),
1101 XML_GetCurrentLineNumber(g_parser), STRUCT_END_TAG);
1102 }
1103
1104 /* Regression test #3 for SF bug #653180. */
START_TEST(test_line_and_column_numbers_inside_handlers)1105 START_TEST(test_line_and_column_numbers_inside_handlers) {
1106 const char *text = "<a>\n" /* Unix end-of-line */
1107 " <b>\r\n" /* Windows end-of-line */
1108 " <c/>\r" /* Mac OS end-of-line */
1109 " </b>\n"
1110 " <d>\n"
1111 " <f/>\n"
1112 " </d>\n"
1113 "</a>";
1114 const StructDataEntry expected[]
1115 = {{XCS("a"), 0, 1, STRUCT_START_TAG}, {XCS("b"), 2, 2, STRUCT_START_TAG},
1116 {XCS("c"), 4, 3, STRUCT_START_TAG}, {XCS("c"), 8, 3, STRUCT_END_TAG},
1117 {XCS("b"), 2, 4, STRUCT_END_TAG}, {XCS("d"), 2, 5, STRUCT_START_TAG},
1118 {XCS("f"), 4, 6, STRUCT_START_TAG}, {XCS("f"), 8, 6, STRUCT_END_TAG},
1119 {XCS("d"), 2, 7, STRUCT_END_TAG}, {XCS("a"), 0, 8, STRUCT_END_TAG}};
1120 const int expected_count = sizeof(expected) / sizeof(StructDataEntry);
1121 StructData storage;
1122
1123 StructData_Init(&storage);
1124 XML_SetUserData(g_parser, &storage);
1125 XML_SetStartElementHandler(g_parser, start_element_event_handler2);
1126 XML_SetEndElementHandler(g_parser, end_element_event_handler2);
1127 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1128 == XML_STATUS_ERROR)
1129 xml_failure(g_parser);
1130
1131 StructData_CheckItems(&storage, expected, expected_count);
1132 StructData_Dispose(&storage);
1133 }
1134 END_TEST
1135
1136 /* Regression test #4 for SF bug #653180. */
START_TEST(test_line_number_after_error)1137 START_TEST(test_line_number_after_error) {
1138 const char *text = "<a>\n"
1139 " <b>\n"
1140 " </a>"; /* missing </b> */
1141 XML_Size lineno;
1142 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
1143 != XML_STATUS_ERROR)
1144 fail("Expected a parse error");
1145
1146 lineno = XML_GetCurrentLineNumber(g_parser);
1147 if (lineno != 3) {
1148 char buffer[100];
1149 sprintf(buffer, "expected 3 lines, saw %" XML_FMT_INT_MOD "u", lineno);
1150 fail(buffer);
1151 }
1152 }
1153 END_TEST
1154
1155 /* Regression test #5 for SF bug #653180. */
START_TEST(test_column_number_after_error)1156 START_TEST(test_column_number_after_error) {
1157 const char *text = "<a>\n"
1158 " <b>\n"
1159 " </a>"; /* missing </b> */
1160 XML_Size colno;
1161 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
1162 != XML_STATUS_ERROR)
1163 fail("Expected a parse error");
1164
1165 colno = XML_GetCurrentColumnNumber(g_parser);
1166 if (colno != 4) {
1167 char buffer[100];
1168 sprintf(buffer, "expected 4 columns, saw %" XML_FMT_INT_MOD "u", colno);
1169 fail(buffer);
1170 }
1171 }
1172 END_TEST
1173
1174 /* Regression test for SF bug #478332. */
START_TEST(test_really_long_lines)1175 START_TEST(test_really_long_lines) {
1176 /* This parses an input line longer than INIT_DATA_BUF_SIZE
1177 characters long (defined to be 1024 in xmlparse.c). We take a
1178 really cheesy approach to building the input buffer, because
1179 this avoids writing bugs in buffer-filling code.
1180 */
1181 const char *text
1182 = "<e>"
1183 /* 64 chars */
1184 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1185 /* until we have at least 1024 characters on the line: */
1186 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1187 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1188 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1189 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1190 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1191 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1192 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1193 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1194 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1195 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1196 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1197 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1198 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1199 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1200 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1201 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1202 "</e>";
1203 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1204 == XML_STATUS_ERROR)
1205 xml_failure(g_parser);
1206 }
1207 END_TEST
1208
1209 /* Test cdata processing across a buffer boundary */
START_TEST(test_really_long_encoded_lines)1210 START_TEST(test_really_long_encoded_lines) {
1211 /* As above, except that we want to provoke an output buffer
1212 * overflow with a non-trivial encoding. For this we need to pass
1213 * the whole cdata in one go, not byte-by-byte.
1214 */
1215 void *buffer;
1216 const char *text
1217 = "<?xml version='1.0' encoding='iso-8859-1'?>"
1218 "<e>"
1219 /* 64 chars */
1220 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1221 /* until we have at least 1024 characters on the line: */
1222 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1223 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1224 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1225 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1226 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1227 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1228 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1229 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1230 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1231 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1232 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1233 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1234 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1235 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1236 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1237 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1238 "</e>";
1239 int parse_len = (int)strlen(text);
1240
1241 /* Need a cdata handler to provoke the code path we want to test */
1242 XML_SetCharacterDataHandler(g_parser, dummy_cdata_handler);
1243 buffer = XML_GetBuffer(g_parser, parse_len);
1244 if (buffer == NULL)
1245 fail("Could not allocate parse buffer");
1246 assert(buffer != NULL);
1247 memcpy(buffer, text, parse_len);
1248 if (XML_ParseBuffer(g_parser, parse_len, XML_TRUE) == XML_STATUS_ERROR)
1249 xml_failure(g_parser);
1250 }
1251 END_TEST
1252
1253 /*
1254 * Element event tests.
1255 */
1256
1257 static void XMLCALL
start_element_event_handler(void * userData,const XML_Char * name,const XML_Char ** atts)1258 start_element_event_handler(void *userData, const XML_Char *name,
1259 const XML_Char **atts) {
1260 UNUSED_P(atts);
1261 CharData_AppendXMLChars((CharData *)userData, name, -1);
1262 }
1263
1264 static void XMLCALL
end_element_event_handler(void * userData,const XML_Char * name)1265 end_element_event_handler(void *userData, const XML_Char *name) {
1266 CharData *storage = (CharData *)userData;
1267 CharData_AppendXMLChars(storage, XCS("/"), 1);
1268 CharData_AppendXMLChars(storage, name, -1);
1269 }
1270
START_TEST(test_end_element_events)1271 START_TEST(test_end_element_events) {
1272 const char *text = "<a><b><c/></b><d><f/></d></a>";
1273 const XML_Char *expected = XCS("/c/b/f/d/a");
1274 CharData storage;
1275
1276 CharData_Init(&storage);
1277 XML_SetUserData(g_parser, &storage);
1278 XML_SetEndElementHandler(g_parser, end_element_event_handler);
1279 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1280 == XML_STATUS_ERROR)
1281 xml_failure(g_parser);
1282 CharData_CheckXMLChars(&storage, expected);
1283 }
1284 END_TEST
1285
1286 /*
1287 * Attribute tests.
1288 */
1289
1290 /* Helpers used by the following test; this checks any "attr" and "refs"
1291 attributes to make sure whitespace has been normalized.
1292
1293 Return true if whitespace has been normalized in a string, using
1294 the rules for attribute value normalization. The 'is_cdata' flag
1295 is needed since CDATA attributes don't need to have multiple
1296 whitespace characters collapsed to a single space, while other
1297 attribute data types do. (Section 3.3.3 of the recommendation.)
1298 */
1299 static int
is_whitespace_normalized(const XML_Char * s,int is_cdata)1300 is_whitespace_normalized(const XML_Char *s, int is_cdata) {
1301 int blanks = 0;
1302 int at_start = 1;
1303 while (*s) {
1304 if (*s == XCS(' '))
1305 ++blanks;
1306 else if (*s == XCS('\t') || *s == XCS('\n') || *s == XCS('\r'))
1307 return 0;
1308 else {
1309 if (at_start) {
1310 at_start = 0;
1311 if (blanks && ! is_cdata)
1312 /* illegal leading blanks */
1313 return 0;
1314 } else if (blanks > 1 && ! is_cdata)
1315 return 0;
1316 blanks = 0;
1317 }
1318 ++s;
1319 }
1320 if (blanks && ! is_cdata)
1321 return 0;
1322 return 1;
1323 }
1324
1325 /* Check the attribute whitespace checker: */
1326 static void
testhelper_is_whitespace_normalized(void)1327 testhelper_is_whitespace_normalized(void) {
1328 assert(is_whitespace_normalized(XCS("abc"), 0));
1329 assert(is_whitespace_normalized(XCS("abc"), 1));
1330 assert(is_whitespace_normalized(XCS("abc def ghi"), 0));
1331 assert(is_whitespace_normalized(XCS("abc def ghi"), 1));
1332 assert(! is_whitespace_normalized(XCS(" abc def ghi"), 0));
1333 assert(is_whitespace_normalized(XCS(" abc def ghi"), 1));
1334 assert(! is_whitespace_normalized(XCS("abc def ghi"), 0));
1335 assert(is_whitespace_normalized(XCS("abc def ghi"), 1));
1336 assert(! is_whitespace_normalized(XCS("abc def ghi "), 0));
1337 assert(is_whitespace_normalized(XCS("abc def ghi "), 1));
1338 assert(! is_whitespace_normalized(XCS(" "), 0));
1339 assert(is_whitespace_normalized(XCS(" "), 1));
1340 assert(! is_whitespace_normalized(XCS("\t"), 0));
1341 assert(! is_whitespace_normalized(XCS("\t"), 1));
1342 assert(! is_whitespace_normalized(XCS("\n"), 0));
1343 assert(! is_whitespace_normalized(XCS("\n"), 1));
1344 assert(! is_whitespace_normalized(XCS("\r"), 0));
1345 assert(! is_whitespace_normalized(XCS("\r"), 1));
1346 assert(! is_whitespace_normalized(XCS("abc\t def"), 1));
1347 }
1348
1349 static void XMLCALL
check_attr_contains_normalized_whitespace(void * userData,const XML_Char * name,const XML_Char ** atts)1350 check_attr_contains_normalized_whitespace(void *userData, const XML_Char *name,
1351 const XML_Char **atts) {
1352 int i;
1353 UNUSED_P(userData);
1354 UNUSED_P(name);
1355 for (i = 0; atts[i] != NULL; i += 2) {
1356 const XML_Char *attrname = atts[i];
1357 const XML_Char *value = atts[i + 1];
1358 if (xcstrcmp(XCS("attr"), attrname) == 0
1359 || xcstrcmp(XCS("ents"), attrname) == 0
1360 || xcstrcmp(XCS("refs"), attrname) == 0) {
1361 if (! is_whitespace_normalized(value, 0)) {
1362 char buffer[256];
1363 sprintf(buffer,
1364 "attribute value not normalized: %" XML_FMT_STR
1365 "='%" XML_FMT_STR "'",
1366 attrname, value);
1367 fail(buffer);
1368 }
1369 }
1370 }
1371 }
1372
START_TEST(test_attr_whitespace_normalization)1373 START_TEST(test_attr_whitespace_normalization) {
1374 const char *text
1375 = "<!DOCTYPE doc [\n"
1376 " <!ATTLIST doc\n"
1377 " attr NMTOKENS #REQUIRED\n"
1378 " ents ENTITIES #REQUIRED\n"
1379 " refs IDREFS #REQUIRED>\n"
1380 "]>\n"
1381 "<doc attr=' a b c\t\td\te\t' refs=' id-1 \t id-2\t\t' \n"
1382 " ents=' ent-1 \t\r\n"
1383 " ent-2 ' >\n"
1384 " <e id='id-1'/>\n"
1385 " <e id='id-2'/>\n"
1386 "</doc>";
1387
1388 XML_SetStartElementHandler(g_parser,
1389 check_attr_contains_normalized_whitespace);
1390 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1391 == XML_STATUS_ERROR)
1392 xml_failure(g_parser);
1393 }
1394 END_TEST
1395
1396 /*
1397 * XML declaration tests.
1398 */
1399
START_TEST(test_xmldecl_misplaced)1400 START_TEST(test_xmldecl_misplaced) {
1401 expect_failure("\n"
1402 "<?xml version='1.0'?>\n"
1403 "<a/>",
1404 XML_ERROR_MISPLACED_XML_PI,
1405 "failed to report misplaced XML declaration");
1406 }
1407 END_TEST
1408
START_TEST(test_xmldecl_invalid)1409 START_TEST(test_xmldecl_invalid) {
1410 expect_failure("<?xml version='1.0' \xc3\xa7?>\n<doc/>", XML_ERROR_XML_DECL,
1411 "Failed to report invalid XML declaration");
1412 }
1413 END_TEST
1414
START_TEST(test_xmldecl_missing_attr)1415 START_TEST(test_xmldecl_missing_attr) {
1416 expect_failure("<?xml ='1.0'?>\n<doc/>\n", XML_ERROR_XML_DECL,
1417 "Failed to report missing XML declaration attribute");
1418 }
1419 END_TEST
1420
START_TEST(test_xmldecl_missing_value)1421 START_TEST(test_xmldecl_missing_value) {
1422 expect_failure("<?xml version='1.0' encoding='us-ascii' standalone?>\n"
1423 "<doc/>",
1424 XML_ERROR_XML_DECL,
1425 "Failed to report missing attribute value");
1426 }
1427 END_TEST
1428
1429 /* Regression test for SF bug #584832. */
1430 static int XMLCALL
UnknownEncodingHandler(void * data,const XML_Char * encoding,XML_Encoding * info)1431 UnknownEncodingHandler(void *data, const XML_Char *encoding,
1432 XML_Encoding *info) {
1433 UNUSED_P(data);
1434 if (xcstrcmp(encoding, XCS("unsupported-encoding")) == 0) {
1435 int i;
1436 for (i = 0; i < 256; ++i)
1437 info->map[i] = i;
1438 info->data = NULL;
1439 info->convert = NULL;
1440 info->release = NULL;
1441 return XML_STATUS_OK;
1442 }
1443 return XML_STATUS_ERROR;
1444 }
1445
START_TEST(test_unknown_encoding_internal_entity)1446 START_TEST(test_unknown_encoding_internal_entity) {
1447 const char *text = "<?xml version='1.0' encoding='unsupported-encoding'?>\n"
1448 "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n"
1449 "<test a='&foo;'/>";
1450
1451 XML_SetUnknownEncodingHandler(g_parser, UnknownEncodingHandler, NULL);
1452 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1453 == XML_STATUS_ERROR)
1454 xml_failure(g_parser);
1455 }
1456 END_TEST
1457
1458 /* Test unrecognised encoding handler */
1459 static void
dummy_release(void * data)1460 dummy_release(void *data) {
1461 UNUSED_P(data);
1462 }
1463
1464 static int XMLCALL
UnrecognisedEncodingHandler(void * data,const XML_Char * encoding,XML_Encoding * info)1465 UnrecognisedEncodingHandler(void *data, const XML_Char *encoding,
1466 XML_Encoding *info) {
1467 UNUSED_P(data);
1468 UNUSED_P(encoding);
1469 info->data = NULL;
1470 info->convert = NULL;
1471 info->release = dummy_release;
1472 return XML_STATUS_ERROR;
1473 }
1474
START_TEST(test_unrecognised_encoding_internal_entity)1475 START_TEST(test_unrecognised_encoding_internal_entity) {
1476 const char *text = "<?xml version='1.0' encoding='unsupported-encoding'?>\n"
1477 "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n"
1478 "<test a='&foo;'/>";
1479
1480 XML_SetUnknownEncodingHandler(g_parser, UnrecognisedEncodingHandler, NULL);
1481 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1482 != XML_STATUS_ERROR)
1483 fail("Unrecognised encoding not rejected");
1484 }
1485 END_TEST
1486
1487 /* Regression test for SF bug #620106. */
1488 static int XMLCALL
external_entity_loader(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)1489 external_entity_loader(XML_Parser parser, const XML_Char *context,
1490 const XML_Char *base, const XML_Char *systemId,
1491 const XML_Char *publicId) {
1492 ExtTest *test_data = (ExtTest *)XML_GetUserData(parser);
1493 XML_Parser extparser;
1494
1495 UNUSED_P(base);
1496 UNUSED_P(systemId);
1497 UNUSED_P(publicId);
1498 extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
1499 if (extparser == NULL)
1500 fail("Could not create external entity parser.");
1501 if (test_data->encoding != NULL) {
1502 if (! XML_SetEncoding(extparser, test_data->encoding))
1503 fail("XML_SetEncoding() ignored for external entity");
1504 }
1505 if (_XML_Parse_SINGLE_BYTES(extparser, test_data->parse_text,
1506 (int)strlen(test_data->parse_text), XML_TRUE)
1507 == XML_STATUS_ERROR) {
1508 xml_failure(extparser);
1509 return XML_STATUS_ERROR;
1510 }
1511 XML_ParserFree(extparser);
1512 return XML_STATUS_OK;
1513 }
1514
START_TEST(test_ext_entity_set_encoding)1515 START_TEST(test_ext_entity_set_encoding) {
1516 const char *text = "<!DOCTYPE doc [\n"
1517 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1518 "]>\n"
1519 "<doc>&en;</doc>";
1520 ExtTest test_data
1521 = {/* This text says it's an unsupported encoding, but it's really
1522 UTF-8, which we tell Expat using XML_SetEncoding().
1523 */
1524 "<?xml encoding='iso-8859-3'?>\xC3\xA9", XCS("utf-8"), NULL};
1525 #ifdef XML_UNICODE
1526 const XML_Char *expected = XCS("\x00e9");
1527 #else
1528 const XML_Char *expected = XCS("\xc3\xa9");
1529 #endif
1530
1531 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1532 run_ext_character_check(text, &test_data, expected);
1533 }
1534 END_TEST
1535
1536 /* Test external entities with no handler */
START_TEST(test_ext_entity_no_handler)1537 START_TEST(test_ext_entity_no_handler) {
1538 const char *text = "<!DOCTYPE doc [\n"
1539 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1540 "]>\n"
1541 "<doc>&en;</doc>";
1542
1543 XML_SetDefaultHandler(g_parser, dummy_default_handler);
1544 run_character_check(text, XCS(""));
1545 }
1546 END_TEST
1547
1548 /* Test UTF-8 BOM is accepted */
START_TEST(test_ext_entity_set_bom)1549 START_TEST(test_ext_entity_set_bom) {
1550 const char *text = "<!DOCTYPE doc [\n"
1551 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1552 "]>\n"
1553 "<doc>&en;</doc>";
1554 ExtTest test_data = {"\xEF\xBB\xBF" /* BOM */
1555 "<?xml encoding='iso-8859-3'?>"
1556 "\xC3\xA9",
1557 XCS("utf-8"), NULL};
1558 #ifdef XML_UNICODE
1559 const XML_Char *expected = XCS("\x00e9");
1560 #else
1561 const XML_Char *expected = XCS("\xc3\xa9");
1562 #endif
1563
1564 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1565 run_ext_character_check(text, &test_data, expected);
1566 }
1567 END_TEST
1568
1569 /* Test that bad encodings are faulted */
1570 typedef struct ext_faults {
1571 const char *parse_text;
1572 const char *fail_text;
1573 const XML_Char *encoding;
1574 enum XML_Error error;
1575 } ExtFaults;
1576
1577 static int XMLCALL
external_entity_faulter(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)1578 external_entity_faulter(XML_Parser parser, const XML_Char *context,
1579 const XML_Char *base, const XML_Char *systemId,
1580 const XML_Char *publicId) {
1581 XML_Parser ext_parser;
1582 ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser);
1583
1584 UNUSED_P(base);
1585 UNUSED_P(systemId);
1586 UNUSED_P(publicId);
1587 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
1588 if (ext_parser == NULL)
1589 fail("Could not create external entity parser");
1590 if (fault->encoding != NULL) {
1591 if (! XML_SetEncoding(ext_parser, fault->encoding))
1592 fail("XML_SetEncoding failed");
1593 }
1594 if (_XML_Parse_SINGLE_BYTES(ext_parser, fault->parse_text,
1595 (int)strlen(fault->parse_text), XML_TRUE)
1596 != XML_STATUS_ERROR)
1597 fail(fault->fail_text);
1598 if (XML_GetErrorCode(ext_parser) != fault->error)
1599 xml_failure(ext_parser);
1600
1601 XML_ParserFree(ext_parser);
1602 return XML_STATUS_ERROR;
1603 }
1604
START_TEST(test_ext_entity_bad_encoding)1605 START_TEST(test_ext_entity_bad_encoding) {
1606 const char *text = "<!DOCTYPE doc [\n"
1607 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1608 "]>\n"
1609 "<doc>&en;</doc>";
1610 ExtFaults fault
1611 = {"<?xml encoding='iso-8859-3'?>u", "Unsupported encoding not faulted",
1612 XCS("unknown"), XML_ERROR_UNKNOWN_ENCODING};
1613
1614 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
1615 XML_SetUserData(g_parser, &fault);
1616 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
1617 "Bad encoding should not have been accepted");
1618 }
1619 END_TEST
1620
1621 /* Try handing an invalid encoding to an external entity parser */
START_TEST(test_ext_entity_bad_encoding_2)1622 START_TEST(test_ext_entity_bad_encoding_2) {
1623 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
1624 "<!DOCTYPE doc SYSTEM 'foo'>\n"
1625 "<doc>&entity;</doc>";
1626 ExtFaults fault
1627 = {"<!ELEMENT doc (#PCDATA)*>", "Unknown encoding not faulted",
1628 XCS("unknown-encoding"), XML_ERROR_UNKNOWN_ENCODING};
1629
1630 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1631 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
1632 XML_SetUserData(g_parser, &fault);
1633 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
1634 "Bad encoding not faulted in external entity handler");
1635 }
1636 END_TEST
1637
1638 /* Test that no error is reported for unknown entities if we don't
1639 read an external subset. This was fixed in Expat 1.95.5.
1640 */
START_TEST(test_wfc_undeclared_entity_unread_external_subset)1641 START_TEST(test_wfc_undeclared_entity_unread_external_subset) {
1642 const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
1643 "<doc>&entity;</doc>";
1644
1645 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1646 == XML_STATUS_ERROR)
1647 xml_failure(g_parser);
1648 }
1649 END_TEST
1650
1651 /* Test that an error is reported for unknown entities if we don't
1652 have an external subset.
1653 */
START_TEST(test_wfc_undeclared_entity_no_external_subset)1654 START_TEST(test_wfc_undeclared_entity_no_external_subset) {
1655 expect_failure("<doc>&entity;</doc>", XML_ERROR_UNDEFINED_ENTITY,
1656 "Parser did not report undefined entity w/out a DTD.");
1657 }
1658 END_TEST
1659
1660 /* Test that an error is reported for unknown entities if we don't
1661 read an external subset, but have been declared standalone.
1662 */
START_TEST(test_wfc_undeclared_entity_standalone)1663 START_TEST(test_wfc_undeclared_entity_standalone) {
1664 const char *text
1665 = "<?xml version='1.0' encoding='us-ascii' standalone='yes'?>\n"
1666 "<!DOCTYPE doc SYSTEM 'foo'>\n"
1667 "<doc>&entity;</doc>";
1668
1669 expect_failure(text, XML_ERROR_UNDEFINED_ENTITY,
1670 "Parser did not report undefined entity (standalone).");
1671 }
1672 END_TEST
1673
1674 /* Test that an error is reported for unknown entities if we have read
1675 an external subset, and standalone is true.
1676 */
START_TEST(test_wfc_undeclared_entity_with_external_subset_standalone)1677 START_TEST(test_wfc_undeclared_entity_with_external_subset_standalone) {
1678 const char *text
1679 = "<?xml version='1.0' encoding='us-ascii' standalone='yes'?>\n"
1680 "<!DOCTYPE doc SYSTEM 'foo'>\n"
1681 "<doc>&entity;</doc>";
1682 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
1683
1684 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1685 XML_SetUserData(g_parser, &test_data);
1686 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1687 expect_failure(text, XML_ERROR_UNDEFINED_ENTITY,
1688 "Parser did not report undefined entity (external DTD).");
1689 }
1690 END_TEST
1691
1692 /* Test that external entity handling is not done if the parsing flag
1693 * is set to UNLESS_STANDALONE
1694 */
START_TEST(test_entity_with_external_subset_unless_standalone)1695 START_TEST(test_entity_with_external_subset_unless_standalone) {
1696 const char *text
1697 = "<?xml version='1.0' encoding='us-ascii' standalone='yes'?>\n"
1698 "<!DOCTYPE doc SYSTEM 'foo'>\n"
1699 "<doc>&entity;</doc>";
1700 ExtTest test_data = {"<!ENTITY entity 'bar'>", NULL, NULL};
1701
1702 XML_SetParamEntityParsing(g_parser,
1703 XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE);
1704 XML_SetUserData(g_parser, &test_data);
1705 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1706 expect_failure(text, XML_ERROR_UNDEFINED_ENTITY,
1707 "Parser did not report undefined entity");
1708 }
1709 END_TEST
1710
1711 /* Test that no error is reported for unknown entities if we have read
1712 an external subset, and standalone is false.
1713 */
START_TEST(test_wfc_undeclared_entity_with_external_subset)1714 START_TEST(test_wfc_undeclared_entity_with_external_subset) {
1715 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
1716 "<!DOCTYPE doc SYSTEM 'foo'>\n"
1717 "<doc>&entity;</doc>";
1718 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
1719
1720 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1721 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1722 run_ext_character_check(text, &test_data, XCS(""));
1723 }
1724 END_TEST
1725
1726 /* Test that an error is reported if our NotStandalone handler fails */
1727 static int XMLCALL
reject_not_standalone_handler(void * userData)1728 reject_not_standalone_handler(void *userData) {
1729 UNUSED_P(userData);
1730 return XML_STATUS_ERROR;
1731 }
1732
START_TEST(test_not_standalone_handler_reject)1733 START_TEST(test_not_standalone_handler_reject) {
1734 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
1735 "<!DOCTYPE doc SYSTEM 'foo'>\n"
1736 "<doc>&entity;</doc>";
1737 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
1738
1739 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1740 XML_SetUserData(g_parser, &test_data);
1741 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1742 XML_SetNotStandaloneHandler(g_parser, reject_not_standalone_handler);
1743 expect_failure(text, XML_ERROR_NOT_STANDALONE,
1744 "NotStandalone handler failed to reject");
1745
1746 /* Try again but without external entity handling */
1747 XML_ParserReset(g_parser, NULL);
1748 XML_SetNotStandaloneHandler(g_parser, reject_not_standalone_handler);
1749 expect_failure(text, XML_ERROR_NOT_STANDALONE,
1750 "NotStandalone handler failed to reject");
1751 }
1752 END_TEST
1753
1754 /* Test that no error is reported if our NotStandalone handler succeeds */
1755 static int XMLCALL
accept_not_standalone_handler(void * userData)1756 accept_not_standalone_handler(void *userData) {
1757 UNUSED_P(userData);
1758 return XML_STATUS_OK;
1759 }
1760
START_TEST(test_not_standalone_handler_accept)1761 START_TEST(test_not_standalone_handler_accept) {
1762 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
1763 "<!DOCTYPE doc SYSTEM 'foo'>\n"
1764 "<doc>&entity;</doc>";
1765 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
1766
1767 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1768 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1769 XML_SetNotStandaloneHandler(g_parser, accept_not_standalone_handler);
1770 run_ext_character_check(text, &test_data, XCS(""));
1771
1772 /* Repeat wtihout the external entity handler */
1773 XML_ParserReset(g_parser, NULL);
1774 XML_SetNotStandaloneHandler(g_parser, accept_not_standalone_handler);
1775 run_character_check(text, XCS(""));
1776 }
1777 END_TEST
1778
START_TEST(test_wfc_no_recursive_entity_refs)1779 START_TEST(test_wfc_no_recursive_entity_refs) {
1780 const char *text = "<!DOCTYPE doc [\n"
1781 " <!ENTITY entity '&entity;'>\n"
1782 "]>\n"
1783 "<doc>&entity;</doc>";
1784
1785 expect_failure(text, XML_ERROR_RECURSIVE_ENTITY_REF,
1786 "Parser did not report recursive entity reference.");
1787 }
1788 END_TEST
1789
1790 /* Test incomplete external entities are faulted */
START_TEST(test_ext_entity_invalid_parse)1791 START_TEST(test_ext_entity_invalid_parse) {
1792 const char *text = "<!DOCTYPE doc [\n"
1793 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1794 "]>\n"
1795 "<doc>&en;</doc>";
1796 const ExtFaults faults[]
1797 = {{"<", "Incomplete element declaration not faulted", NULL,
1798 XML_ERROR_UNCLOSED_TOKEN},
1799 {"<\xe2\x82", /* First two bytes of a three-byte char */
1800 "Incomplete character not faulted", NULL, XML_ERROR_PARTIAL_CHAR},
1801 {"<tag>\xe2\x82", "Incomplete character in CDATA not faulted", NULL,
1802 XML_ERROR_PARTIAL_CHAR},
1803 {NULL, NULL, NULL, XML_ERROR_NONE}};
1804 const ExtFaults *fault = faults;
1805
1806 for (; fault->parse_text != NULL; fault++) {
1807 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1808 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
1809 XML_SetUserData(g_parser, (void *)fault);
1810 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
1811 "Parser did not report external entity error");
1812 XML_ParserReset(g_parser, NULL);
1813 }
1814 }
1815 END_TEST
1816
1817 /* Regression test for SF bug #483514. */
START_TEST(test_dtd_default_handling)1818 START_TEST(test_dtd_default_handling) {
1819 const char *text = "<!DOCTYPE doc [\n"
1820 "<!ENTITY e SYSTEM 'http://example.org/e'>\n"
1821 "<!NOTATION n SYSTEM 'http://example.org/n'>\n"
1822 "<!ELEMENT doc EMPTY>\n"
1823 "<!ATTLIST doc a CDATA #IMPLIED>\n"
1824 "<?pi in dtd?>\n"
1825 "<!--comment in dtd-->\n"
1826 "]><doc/>";
1827
1828 XML_SetDefaultHandler(g_parser, accumulate_characters);
1829 XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler);
1830 XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler);
1831 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
1832 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
1833 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
1834 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
1835 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
1836 XML_SetCommentHandler(g_parser, dummy_comment_handler);
1837 XML_SetStartCdataSectionHandler(g_parser, dummy_start_cdata_handler);
1838 XML_SetEndCdataSectionHandler(g_parser, dummy_end_cdata_handler);
1839 run_character_check(text, XCS("\n\n\n\n\n\n\n<doc/>"));
1840 }
1841 END_TEST
1842
1843 /* Test handling of attribute declarations */
1844 typedef struct AttTest {
1845 const char *definition;
1846 const XML_Char *element_name;
1847 const XML_Char *attr_name;
1848 const XML_Char *attr_type;
1849 const XML_Char *default_value;
1850 int is_required;
1851 } AttTest;
1852
1853 static void XMLCALL
verify_attlist_decl_handler(void * userData,const XML_Char * element_name,const XML_Char * attr_name,const XML_Char * attr_type,const XML_Char * default_value,int is_required)1854 verify_attlist_decl_handler(void *userData, const XML_Char *element_name,
1855 const XML_Char *attr_name,
1856 const XML_Char *attr_type,
1857 const XML_Char *default_value, int is_required) {
1858 AttTest *at = (AttTest *)userData;
1859
1860 if (xcstrcmp(element_name, at->element_name))
1861 fail("Unexpected element name in attribute declaration");
1862 if (xcstrcmp(attr_name, at->attr_name))
1863 fail("Unexpected attribute name in attribute declaration");
1864 if (xcstrcmp(attr_type, at->attr_type))
1865 fail("Unexpected attribute type in attribute declaration");
1866 if ((default_value == NULL && at->default_value != NULL)
1867 || (default_value != NULL && at->default_value == NULL)
1868 || (default_value != NULL && xcstrcmp(default_value, at->default_value)))
1869 fail("Unexpected default value in attribute declaration");
1870 if (is_required != at->is_required)
1871 fail("Requirement mismatch in attribute declaration");
1872 }
1873
START_TEST(test_dtd_attr_handling)1874 START_TEST(test_dtd_attr_handling) {
1875 const char *prolog = "<!DOCTYPE doc [\n"
1876 "<!ELEMENT doc EMPTY>\n";
1877 AttTest attr_data[]
1878 = {{"<!ATTLIST doc a ( one | two | three ) #REQUIRED>\n"
1879 "]>"
1880 "<doc a='two'/>",
1881 XCS("doc"), XCS("a"),
1882 XCS("(one|two|three)"), /* Extraneous spaces will be removed */
1883 NULL, XML_TRUE},
1884 {"<!NOTATION foo SYSTEM 'http://example.org/foo'>\n"
1885 "<!ATTLIST doc a NOTATION (foo) #IMPLIED>\n"
1886 "]>"
1887 "<doc/>",
1888 XCS("doc"), XCS("a"), XCS("NOTATION(foo)"), NULL, XML_FALSE},
1889 {"<!ATTLIST doc a NOTATION (foo) 'bar'>\n"
1890 "]>"
1891 "<doc/>",
1892 XCS("doc"), XCS("a"), XCS("NOTATION(foo)"), XCS("bar"), XML_FALSE},
1893 {"<!ATTLIST doc a CDATA '\xdb\xb2'>\n"
1894 "]>"
1895 "<doc/>",
1896 XCS("doc"), XCS("a"), XCS("CDATA"),
1897 #ifdef XML_UNICODE
1898 XCS("\x06f2"),
1899 #else
1900 XCS("\xdb\xb2"),
1901 #endif
1902 XML_FALSE},
1903 {NULL, NULL, NULL, NULL, NULL, XML_FALSE}};
1904 AttTest *test;
1905
1906 for (test = attr_data; test->definition != NULL; test++) {
1907 XML_SetAttlistDeclHandler(g_parser, verify_attlist_decl_handler);
1908 XML_SetUserData(g_parser, test);
1909 if (_XML_Parse_SINGLE_BYTES(g_parser, prolog, (int)strlen(prolog),
1910 XML_FALSE)
1911 == XML_STATUS_ERROR)
1912 xml_failure(g_parser);
1913 if (_XML_Parse_SINGLE_BYTES(g_parser, test->definition,
1914 (int)strlen(test->definition), XML_TRUE)
1915 == XML_STATUS_ERROR)
1916 xml_failure(g_parser);
1917 XML_ParserReset(g_parser, NULL);
1918 }
1919 }
1920 END_TEST
1921
1922 /* See related SF bug #673791.
1923 When namespace processing is enabled, setting the namespace URI for
1924 a prefix is not allowed; this test ensures that it *is* allowed
1925 when namespace processing is not enabled.
1926 (See Namespaces in XML, section 2.)
1927 */
START_TEST(test_empty_ns_without_namespaces)1928 START_TEST(test_empty_ns_without_namespaces) {
1929 const char *text = "<doc xmlns:prefix='http://example.org/'>\n"
1930 " <e xmlns:prefix=''/>\n"
1931 "</doc>";
1932
1933 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1934 == XML_STATUS_ERROR)
1935 xml_failure(g_parser);
1936 }
1937 END_TEST
1938
1939 /* Regression test for SF bug #824420.
1940 Checks that an xmlns:prefix attribute set in an attribute's default
1941 value isn't misinterpreted.
1942 */
START_TEST(test_ns_in_attribute_default_without_namespaces)1943 START_TEST(test_ns_in_attribute_default_without_namespaces) {
1944 const char *text = "<!DOCTYPE e:element [\n"
1945 " <!ATTLIST e:element\n"
1946 " xmlns:e CDATA 'http://example.org/'>\n"
1947 " ]>\n"
1948 "<e:element/>";
1949
1950 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1951 == XML_STATUS_ERROR)
1952 xml_failure(g_parser);
1953 }
1954 END_TEST
1955
1956 static const char *long_character_data_text
1957 = "<?xml version='1.0' encoding='iso-8859-1'?><s>"
1958 "012345678901234567890123456789012345678901234567890123456789"
1959 "012345678901234567890123456789012345678901234567890123456789"
1960 "012345678901234567890123456789012345678901234567890123456789"
1961 "012345678901234567890123456789012345678901234567890123456789"
1962 "012345678901234567890123456789012345678901234567890123456789"
1963 "012345678901234567890123456789012345678901234567890123456789"
1964 "012345678901234567890123456789012345678901234567890123456789"
1965 "012345678901234567890123456789012345678901234567890123456789"
1966 "012345678901234567890123456789012345678901234567890123456789"
1967 "012345678901234567890123456789012345678901234567890123456789"
1968 "012345678901234567890123456789012345678901234567890123456789"
1969 "012345678901234567890123456789012345678901234567890123456789"
1970 "012345678901234567890123456789012345678901234567890123456789"
1971 "012345678901234567890123456789012345678901234567890123456789"
1972 "012345678901234567890123456789012345678901234567890123456789"
1973 "012345678901234567890123456789012345678901234567890123456789"
1974 "012345678901234567890123456789012345678901234567890123456789"
1975 "012345678901234567890123456789012345678901234567890123456789"
1976 "012345678901234567890123456789012345678901234567890123456789"
1977 "012345678901234567890123456789012345678901234567890123456789"
1978 "</s>";
1979
1980 static XML_Bool resumable = XML_FALSE;
1981
1982 static void
clearing_aborting_character_handler(void * userData,const XML_Char * s,int len)1983 clearing_aborting_character_handler(void *userData, const XML_Char *s,
1984 int len) {
1985 UNUSED_P(userData);
1986 UNUSED_P(s);
1987 UNUSED_P(len);
1988 XML_StopParser(g_parser, resumable);
1989 XML_SetCharacterDataHandler(g_parser, NULL);
1990 }
1991
1992 /* Regression test for SF bug #1515266: missing check of stopped
1993 parser in doContext() 'for' loop. */
START_TEST(test_stop_parser_between_char_data_calls)1994 START_TEST(test_stop_parser_between_char_data_calls) {
1995 /* The sample data must be big enough that there are two calls to
1996 the character data handler from within the inner "for" loop of
1997 the XML_TOK_DATA_CHARS case in doContent(), and the character
1998 handler must stop the parser and clear the character data
1999 handler.
2000 */
2001 const char *text = long_character_data_text;
2002
2003 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2004 resumable = XML_FALSE;
2005 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2006 != XML_STATUS_ERROR)
2007 xml_failure(g_parser);
2008 if (XML_GetErrorCode(g_parser) != XML_ERROR_ABORTED)
2009 xml_failure(g_parser);
2010 }
2011 END_TEST
2012
2013 /* Regression test for SF bug #1515266: missing check of stopped
2014 parser in doContext() 'for' loop. */
START_TEST(test_suspend_parser_between_char_data_calls)2015 START_TEST(test_suspend_parser_between_char_data_calls) {
2016 /* The sample data must be big enough that there are two calls to
2017 the character data handler from within the inner "for" loop of
2018 the XML_TOK_DATA_CHARS case in doContent(), and the character
2019 handler must stop the parser and clear the character data
2020 handler.
2021 */
2022 const char *text = long_character_data_text;
2023
2024 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2025 resumable = XML_TRUE;
2026 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2027 != XML_STATUS_SUSPENDED)
2028 xml_failure(g_parser);
2029 if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE)
2030 xml_failure(g_parser);
2031 /* Try parsing directly */
2032 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
2033 != XML_STATUS_ERROR)
2034 fail("Attempt to continue parse while suspended not faulted");
2035 if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED)
2036 fail("Suspended parse not faulted with correct error");
2037 }
2038 END_TEST
2039
2040 static XML_Bool abortable = XML_FALSE;
2041
2042 static void
parser_stop_character_handler(void * userData,const XML_Char * s,int len)2043 parser_stop_character_handler(void *userData, const XML_Char *s, int len) {
2044 UNUSED_P(userData);
2045 UNUSED_P(s);
2046 UNUSED_P(len);
2047 XML_StopParser(g_parser, resumable);
2048 XML_SetCharacterDataHandler(g_parser, NULL);
2049 if (! resumable) {
2050 /* Check that aborting an aborted parser is faulted */
2051 if (XML_StopParser(g_parser, XML_FALSE) != XML_STATUS_ERROR)
2052 fail("Aborting aborted parser not faulted");
2053 if (XML_GetErrorCode(g_parser) != XML_ERROR_FINISHED)
2054 xml_failure(g_parser);
2055 } else if (abortable) {
2056 /* Check that aborting a suspended parser works */
2057 if (XML_StopParser(g_parser, XML_FALSE) == XML_STATUS_ERROR)
2058 xml_failure(g_parser);
2059 } else {
2060 /* Check that suspending a suspended parser works */
2061 if (XML_StopParser(g_parser, XML_TRUE) != XML_STATUS_ERROR)
2062 fail("Suspending suspended parser not faulted");
2063 if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED)
2064 xml_failure(g_parser);
2065 }
2066 }
2067
2068 /* Test repeated calls to XML_StopParser are handled correctly */
START_TEST(test_repeated_stop_parser_between_char_data_calls)2069 START_TEST(test_repeated_stop_parser_between_char_data_calls) {
2070 const char *text = long_character_data_text;
2071
2072 XML_SetCharacterDataHandler(g_parser, parser_stop_character_handler);
2073 resumable = XML_FALSE;
2074 abortable = XML_FALSE;
2075 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2076 != XML_STATUS_ERROR)
2077 fail("Failed to double-stop parser");
2078
2079 XML_ParserReset(g_parser, NULL);
2080 XML_SetCharacterDataHandler(g_parser, parser_stop_character_handler);
2081 resumable = XML_TRUE;
2082 abortable = XML_FALSE;
2083 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2084 != XML_STATUS_SUSPENDED)
2085 fail("Failed to double-suspend parser");
2086
2087 XML_ParserReset(g_parser, NULL);
2088 XML_SetCharacterDataHandler(g_parser, parser_stop_character_handler);
2089 resumable = XML_TRUE;
2090 abortable = XML_TRUE;
2091 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2092 != XML_STATUS_ERROR)
2093 fail("Failed to suspend-abort parser");
2094 }
2095 END_TEST
2096
START_TEST(test_good_cdata_ascii)2097 START_TEST(test_good_cdata_ascii) {
2098 const char *text = "<a><![CDATA[<greeting>Hello, world!</greeting>]]></a>";
2099 const XML_Char *expected = XCS("<greeting>Hello, world!</greeting>");
2100
2101 CharData storage;
2102 CharData_Init(&storage);
2103 XML_SetUserData(g_parser, &storage);
2104 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2105 /* Add start and end handlers for coverage */
2106 XML_SetStartCdataSectionHandler(g_parser, dummy_start_cdata_handler);
2107 XML_SetEndCdataSectionHandler(g_parser, dummy_end_cdata_handler);
2108
2109 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2110 == XML_STATUS_ERROR)
2111 xml_failure(g_parser);
2112 CharData_CheckXMLChars(&storage, expected);
2113
2114 /* Try again, this time with a default handler */
2115 XML_ParserReset(g_parser, NULL);
2116 CharData_Init(&storage);
2117 XML_SetUserData(g_parser, &storage);
2118 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2119 XML_SetDefaultHandler(g_parser, dummy_default_handler);
2120
2121 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2122 == XML_STATUS_ERROR)
2123 xml_failure(g_parser);
2124 CharData_CheckXMLChars(&storage, expected);
2125 }
2126 END_TEST
2127
START_TEST(test_good_cdata_utf16)2128 START_TEST(test_good_cdata_utf16) {
2129 /* Test data is:
2130 * <?xml version='1.0' encoding='utf-16'?>
2131 * <a><![CDATA[hello]]></a>
2132 */
2133 const char text[]
2134 = "\0<\0?\0x\0m\0l\0"
2135 " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2136 " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0"
2137 "1\0"
2138 "6\0'"
2139 "\0?\0>\0\n"
2140 "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0[\0h\0e\0l\0l\0o\0]\0]\0>\0<\0/\0a\0>";
2141 const XML_Char *expected = XCS("hello");
2142
2143 CharData storage;
2144 CharData_Init(&storage);
2145 XML_SetUserData(g_parser, &storage);
2146 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2147
2148 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
2149 == XML_STATUS_ERROR)
2150 xml_failure(g_parser);
2151 CharData_CheckXMLChars(&storage, expected);
2152 }
2153 END_TEST
2154
START_TEST(test_good_cdata_utf16_le)2155 START_TEST(test_good_cdata_utf16_le) {
2156 /* Test data is:
2157 * <?xml version='1.0' encoding='utf-16'?>
2158 * <a><![CDATA[hello]]></a>
2159 */
2160 const char text[]
2161 = "<\0?\0x\0m\0l\0"
2162 " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2163 " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0"
2164 "1\0"
2165 "6\0'"
2166 "\0?\0>\0\n"
2167 "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0[\0h\0e\0l\0l\0o\0]\0]\0>\0<\0/\0a\0>\0";
2168 const XML_Char *expected = XCS("hello");
2169
2170 CharData storage;
2171 CharData_Init(&storage);
2172 XML_SetUserData(g_parser, &storage);
2173 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2174
2175 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
2176 == XML_STATUS_ERROR)
2177 xml_failure(g_parser);
2178 CharData_CheckXMLChars(&storage, expected);
2179 }
2180 END_TEST
2181
2182 /* Test UTF16 conversion of a long cdata string */
2183
2184 /* 16 characters: handy macro to reduce visual clutter */
2185 #define A_TO_P_IN_UTF16 "\0A\0B\0C\0D\0E\0F\0G\0H\0I\0J\0K\0L\0M\0N\0O\0P"
2186
START_TEST(test_long_cdata_utf16)2187 START_TEST(test_long_cdata_utf16) {
2188 /* Test data is:
2189 * <?xlm version='1.0' encoding='utf-16'?>
2190 * <a><![CDATA[
2191 * ABCDEFGHIJKLMNOP
2192 * ]]></a>
2193 */
2194 const char text[]
2195 = "\0<\0?\0x\0m\0l\0 "
2196 "\0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0 "
2197 "\0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0\x31\0\x36\0'\0?\0>"
2198 "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0["
2199 /* 64 characters per line */
2200 /* clang-format off */
2201 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
2202 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
2203 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
2204 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
2205 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
2206 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
2207 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
2208 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
2209 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
2210 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
2211 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
2212 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
2213 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
2214 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
2215 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
2216 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
2217 A_TO_P_IN_UTF16
2218 /* clang-format on */
2219 "\0]\0]\0>\0<\0/\0a\0>";
2220 const XML_Char *expected =
2221 /* clang-format off */
2222 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2223 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2224 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2225 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2226 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2227 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2228 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2229 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2230 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2231 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2232 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2233 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2234 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2235 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2236 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2237 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2238 XCS("ABCDEFGHIJKLMNOP");
2239 /* clang-format on */
2240 CharData storage;
2241 void *buffer;
2242
2243 CharData_Init(&storage);
2244 XML_SetUserData(g_parser, &storage);
2245 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2246 buffer = XML_GetBuffer(g_parser, sizeof(text) - 1);
2247 if (buffer == NULL)
2248 fail("Could not allocate parse buffer");
2249 assert(buffer != NULL);
2250 memcpy(buffer, text, sizeof(text) - 1);
2251 if (XML_ParseBuffer(g_parser, sizeof(text) - 1, XML_TRUE) == XML_STATUS_ERROR)
2252 xml_failure(g_parser);
2253 CharData_CheckXMLChars(&storage, expected);
2254 }
2255 END_TEST
2256
2257 /* Test handling of multiple unit UTF-16 characters */
START_TEST(test_multichar_cdata_utf16)2258 START_TEST(test_multichar_cdata_utf16) {
2259 /* Test data is:
2260 * <?xml version='1.0' encoding='utf-16'?>
2261 * <a><![CDATA[{MINIM}{CROTCHET}]]></a>
2262 *
2263 * where {MINIM} is U+1d15e (a minim or half-note)
2264 * UTF-16: 0xd834 0xdd5e
2265 * UTF-8: 0xf0 0x9d 0x85 0x9e
2266 * and {CROTCHET} is U+1d15f (a crotchet or quarter-note)
2267 * UTF-16: 0xd834 0xdd5f
2268 * UTF-8: 0xf0 0x9d 0x85 0x9f
2269 */
2270 const char text[] = "\0<\0?\0x\0m\0l\0"
2271 " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2272 " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0"
2273 "1\0"
2274 "6\0'"
2275 "\0?\0>\0\n"
2276 "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0["
2277 "\xd8\x34\xdd\x5e\xd8\x34\xdd\x5f"
2278 "\0]\0]\0>\0<\0/\0a\0>";
2279 #ifdef XML_UNICODE
2280 const XML_Char *expected = XCS("\xd834\xdd5e\xd834\xdd5f");
2281 #else
2282 const XML_Char *expected = XCS("\xf0\x9d\x85\x9e\xf0\x9d\x85\x9f");
2283 #endif
2284 CharData storage;
2285
2286 CharData_Init(&storage);
2287 XML_SetUserData(g_parser, &storage);
2288 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2289
2290 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
2291 == XML_STATUS_ERROR)
2292 xml_failure(g_parser);
2293 CharData_CheckXMLChars(&storage, expected);
2294 }
2295 END_TEST
2296
2297 /* Test that an element name with a UTF-16 surrogate pair is rejected */
START_TEST(test_utf16_bad_surrogate_pair)2298 START_TEST(test_utf16_bad_surrogate_pair) {
2299 /* Test data is:
2300 * <?xml version='1.0' encoding='utf-16'?>
2301 * <a><![CDATA[{BADLINB}]]></a>
2302 *
2303 * where {BADLINB} is U+10000 (the first Linear B character)
2304 * with the UTF-16 surrogate pair in the wrong order, i.e.
2305 * 0xdc00 0xd800
2306 */
2307 const char text[] = "\0<\0?\0x\0m\0l\0"
2308 " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2309 " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0"
2310 "1\0"
2311 "6\0'"
2312 "\0?\0>\0\n"
2313 "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0["
2314 "\xdc\x00\xd8\x00"
2315 "\0]\0]\0>\0<\0/\0a\0>";
2316
2317 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
2318 != XML_STATUS_ERROR)
2319 fail("Reversed UTF-16 surrogate pair not faulted");
2320 if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
2321 xml_failure(g_parser);
2322 }
2323 END_TEST
2324
START_TEST(test_bad_cdata)2325 START_TEST(test_bad_cdata) {
2326 struct CaseData {
2327 const char *text;
2328 enum XML_Error expectedError;
2329 };
2330
2331 struct CaseData cases[]
2332 = {{"<a><", XML_ERROR_UNCLOSED_TOKEN},
2333 {"<a><!", XML_ERROR_UNCLOSED_TOKEN},
2334 {"<a><![", XML_ERROR_UNCLOSED_TOKEN},
2335 {"<a><![C", XML_ERROR_UNCLOSED_TOKEN},
2336 {"<a><![CD", XML_ERROR_UNCLOSED_TOKEN},
2337 {"<a><![CDA", XML_ERROR_UNCLOSED_TOKEN},
2338 {"<a><![CDAT", XML_ERROR_UNCLOSED_TOKEN},
2339 {"<a><![CDATA", XML_ERROR_UNCLOSED_TOKEN},
2340
2341 {"<a><![CDATA[", XML_ERROR_UNCLOSED_CDATA_SECTION},
2342 {"<a><![CDATA[]", XML_ERROR_UNCLOSED_CDATA_SECTION},
2343 {"<a><![CDATA[]]", XML_ERROR_UNCLOSED_CDATA_SECTION},
2344
2345 {"<a><!<a/>", XML_ERROR_INVALID_TOKEN},
2346 {"<a><![<a/>", XML_ERROR_UNCLOSED_TOKEN}, /* ?! */
2347 {"<a><![C<a/>", XML_ERROR_UNCLOSED_TOKEN}, /* ?! */
2348 {"<a><![CD<a/>", XML_ERROR_INVALID_TOKEN},
2349 {"<a><![CDA<a/>", XML_ERROR_INVALID_TOKEN},
2350 {"<a><![CDAT<a/>", XML_ERROR_INVALID_TOKEN},
2351 {"<a><![CDATA<a/>", XML_ERROR_INVALID_TOKEN},
2352
2353 {"<a><![CDATA[<a/>", XML_ERROR_UNCLOSED_CDATA_SECTION},
2354 {"<a><![CDATA[]<a/>", XML_ERROR_UNCLOSED_CDATA_SECTION},
2355 {"<a><![CDATA[]]<a/>", XML_ERROR_UNCLOSED_CDATA_SECTION}};
2356
2357 size_t i = 0;
2358 for (; i < sizeof(cases) / sizeof(struct CaseData); i++) {
2359 const enum XML_Status actualStatus = _XML_Parse_SINGLE_BYTES(
2360 g_parser, cases[i].text, (int)strlen(cases[i].text), XML_TRUE);
2361 const enum XML_Error actualError = XML_GetErrorCode(g_parser);
2362
2363 assert(actualStatus == XML_STATUS_ERROR);
2364
2365 if (actualError != cases[i].expectedError) {
2366 char message[100];
2367 sprintf(message,
2368 "Expected error %d but got error %d for case %u: \"%s\"\n",
2369 cases[i].expectedError, actualError, (unsigned int)i + 1,
2370 cases[i].text);
2371 fail(message);
2372 }
2373
2374 XML_ParserReset(g_parser, NULL);
2375 }
2376 }
2377 END_TEST
2378
2379 /* Test failures in UTF-16 CDATA */
START_TEST(test_bad_cdata_utf16)2380 START_TEST(test_bad_cdata_utf16) {
2381 struct CaseData {
2382 size_t text_bytes;
2383 const char *text;
2384 enum XML_Error expected_error;
2385 };
2386
2387 const char prolog[] = "\0<\0?\0x\0m\0l\0"
2388 " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2389 " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0"
2390 "1\0"
2391 "6\0'"
2392 "\0?\0>\0\n"
2393 "\0<\0a\0>";
2394 struct CaseData cases[] = {
2395 {1, "\0", XML_ERROR_UNCLOSED_TOKEN},
2396 {2, "\0<", XML_ERROR_UNCLOSED_TOKEN},
2397 {3, "\0<\0", XML_ERROR_UNCLOSED_TOKEN},
2398 {4, "\0<\0!", XML_ERROR_UNCLOSED_TOKEN},
2399 {5, "\0<\0!\0", XML_ERROR_UNCLOSED_TOKEN},
2400 {6, "\0<\0!\0[", XML_ERROR_UNCLOSED_TOKEN},
2401 {7, "\0<\0!\0[\0", XML_ERROR_UNCLOSED_TOKEN},
2402 {8, "\0<\0!\0[\0C", XML_ERROR_UNCLOSED_TOKEN},
2403 {9, "\0<\0!\0[\0C\0", XML_ERROR_UNCLOSED_TOKEN},
2404 {10, "\0<\0!\0[\0C\0D", XML_ERROR_UNCLOSED_TOKEN},
2405 {11, "\0<\0!\0[\0C\0D\0", XML_ERROR_UNCLOSED_TOKEN},
2406 {12, "\0<\0!\0[\0C\0D\0A", XML_ERROR_UNCLOSED_TOKEN},
2407 {13, "\0<\0!\0[\0C\0D\0A\0", XML_ERROR_UNCLOSED_TOKEN},
2408 {14, "\0<\0!\0[\0C\0D\0A\0T", XML_ERROR_UNCLOSED_TOKEN},
2409 {15, "\0<\0!\0[\0C\0D\0A\0T\0", XML_ERROR_UNCLOSED_TOKEN},
2410 {16, "\0<\0!\0[\0C\0D\0A\0T\0A", XML_ERROR_UNCLOSED_TOKEN},
2411 {17, "\0<\0!\0[\0C\0D\0A\0T\0A\0", XML_ERROR_UNCLOSED_TOKEN},
2412 {18, "\0<\0!\0[\0C\0D\0A\0T\0A\0[", XML_ERROR_UNCLOSED_CDATA_SECTION},
2413 {19, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0", XML_ERROR_UNCLOSED_CDATA_SECTION},
2414 {20, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z", XML_ERROR_UNCLOSED_CDATA_SECTION},
2415 /* Now add a four-byte UTF-16 character */
2416 {21, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8",
2417 XML_ERROR_UNCLOSED_CDATA_SECTION},
2418 {22, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8\x34", XML_ERROR_PARTIAL_CHAR},
2419 {23, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8\x34\xdd",
2420 XML_ERROR_PARTIAL_CHAR},
2421 {24, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8\x34\xdd\x5e",
2422 XML_ERROR_UNCLOSED_CDATA_SECTION}};
2423 size_t i;
2424
2425 for (i = 0; i < sizeof(cases) / sizeof(struct CaseData); i++) {
2426 enum XML_Status actual_status;
2427 enum XML_Error actual_error;
2428
2429 if (_XML_Parse_SINGLE_BYTES(g_parser, prolog, (int)sizeof(prolog) - 1,
2430 XML_FALSE)
2431 == XML_STATUS_ERROR)
2432 xml_failure(g_parser);
2433 actual_status = _XML_Parse_SINGLE_BYTES(g_parser, cases[i].text,
2434 (int)cases[i].text_bytes, XML_TRUE);
2435 assert(actual_status == XML_STATUS_ERROR);
2436 actual_error = XML_GetErrorCode(g_parser);
2437 if (actual_error != cases[i].expected_error) {
2438 char message[1024];
2439
2440 sprintf(message,
2441 "Expected error %d (%" XML_FMT_STR "), got %d (%" XML_FMT_STR
2442 ") for case %lu\n",
2443 cases[i].expected_error, XML_ErrorString(cases[i].expected_error),
2444 actual_error, XML_ErrorString(actual_error),
2445 (long unsigned)(i + 1));
2446 fail(message);
2447 }
2448 XML_ParserReset(g_parser, NULL);
2449 }
2450 }
2451 END_TEST
2452
2453 static const char *long_cdata_text
2454 = "<s><![CDATA["
2455 "012345678901234567890123456789012345678901234567890123456789"
2456 "012345678901234567890123456789012345678901234567890123456789"
2457 "012345678901234567890123456789012345678901234567890123456789"
2458 "012345678901234567890123456789012345678901234567890123456789"
2459 "012345678901234567890123456789012345678901234567890123456789"
2460 "012345678901234567890123456789012345678901234567890123456789"
2461 "012345678901234567890123456789012345678901234567890123456789"
2462 "012345678901234567890123456789012345678901234567890123456789"
2463 "012345678901234567890123456789012345678901234567890123456789"
2464 "012345678901234567890123456789012345678901234567890123456789"
2465 "012345678901234567890123456789012345678901234567890123456789"
2466 "012345678901234567890123456789012345678901234567890123456789"
2467 "012345678901234567890123456789012345678901234567890123456789"
2468 "012345678901234567890123456789012345678901234567890123456789"
2469 "012345678901234567890123456789012345678901234567890123456789"
2470 "012345678901234567890123456789012345678901234567890123456789"
2471 "012345678901234567890123456789012345678901234567890123456789"
2472 "012345678901234567890123456789012345678901234567890123456789"
2473 "012345678901234567890123456789012345678901234567890123456789"
2474 "012345678901234567890123456789012345678901234567890123456789"
2475 "]]></s>";
2476
2477 /* Test stopping the parser in cdata handler */
START_TEST(test_stop_parser_between_cdata_calls)2478 START_TEST(test_stop_parser_between_cdata_calls) {
2479 const char *text = long_cdata_text;
2480
2481 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2482 resumable = XML_FALSE;
2483 expect_failure(text, XML_ERROR_ABORTED, "Parse not aborted in CDATA handler");
2484 }
2485 END_TEST
2486
2487 /* Test suspending the parser in cdata handler */
START_TEST(test_suspend_parser_between_cdata_calls)2488 START_TEST(test_suspend_parser_between_cdata_calls) {
2489 const char *text = long_cdata_text;
2490 enum XML_Status result;
2491
2492 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2493 resumable = XML_TRUE;
2494 result = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE);
2495 if (result != XML_STATUS_SUSPENDED) {
2496 if (result == XML_STATUS_ERROR)
2497 xml_failure(g_parser);
2498 fail("Parse not suspended in CDATA handler");
2499 }
2500 if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE)
2501 xml_failure(g_parser);
2502 }
2503 END_TEST
2504
2505 /* Test memory allocation functions */
START_TEST(test_memory_allocation)2506 START_TEST(test_memory_allocation) {
2507 char *buffer = (char *)XML_MemMalloc(g_parser, 256);
2508 char *p;
2509
2510 if (buffer == NULL) {
2511 fail("Allocation failed");
2512 } else {
2513 /* Try writing to memory; some OSes try to cheat! */
2514 buffer[0] = 'T';
2515 buffer[1] = 'E';
2516 buffer[2] = 'S';
2517 buffer[3] = 'T';
2518 buffer[4] = '\0';
2519 if (strcmp(buffer, "TEST") != 0) {
2520 fail("Memory not writable");
2521 } else {
2522 p = (char *)XML_MemRealloc(g_parser, buffer, 512);
2523 if (p == NULL) {
2524 fail("Reallocation failed");
2525 } else {
2526 /* Write again, just to be sure */
2527 buffer = p;
2528 buffer[0] = 'V';
2529 if (strcmp(buffer, "VEST") != 0) {
2530 fail("Reallocated memory not writable");
2531 }
2532 }
2533 }
2534 XML_MemFree(g_parser, buffer);
2535 }
2536 }
2537 END_TEST
2538
2539 static void XMLCALL
record_default_handler(void * userData,const XML_Char * s,int len)2540 record_default_handler(void *userData, const XML_Char *s, int len) {
2541 UNUSED_P(s);
2542 UNUSED_P(len);
2543 CharData_AppendXMLChars((CharData *)userData, XCS("D"), 1);
2544 }
2545
2546 static void XMLCALL
record_cdata_handler(void * userData,const XML_Char * s,int len)2547 record_cdata_handler(void *userData, const XML_Char *s, int len) {
2548 UNUSED_P(s);
2549 UNUSED_P(len);
2550 CharData_AppendXMLChars((CharData *)userData, XCS("C"), 1);
2551 XML_DefaultCurrent(g_parser);
2552 }
2553
2554 static void XMLCALL
record_cdata_nodefault_handler(void * userData,const XML_Char * s,int len)2555 record_cdata_nodefault_handler(void *userData, const XML_Char *s, int len) {
2556 UNUSED_P(s);
2557 UNUSED_P(len);
2558 CharData_AppendXMLChars((CharData *)userData, XCS("c"), 1);
2559 }
2560
2561 static void XMLCALL
record_skip_handler(void * userData,const XML_Char * entityName,int is_parameter_entity)2562 record_skip_handler(void *userData, const XML_Char *entityName,
2563 int is_parameter_entity) {
2564 UNUSED_P(entityName);
2565 CharData_AppendXMLChars((CharData *)userData,
2566 is_parameter_entity ? XCS("E") : XCS("e"), 1);
2567 }
2568
2569 /* Test XML_DefaultCurrent() passes handling on correctly */
START_TEST(test_default_current)2570 START_TEST(test_default_current) {
2571 const char *text = "<doc>hell]</doc>";
2572 const char *entity_text = "<!DOCTYPE doc [\n"
2573 "<!ENTITY entity '%'>\n"
2574 "]>\n"
2575 "<doc>&entity;</doc>";
2576 CharData storage;
2577
2578 XML_SetDefaultHandler(g_parser, record_default_handler);
2579 XML_SetCharacterDataHandler(g_parser, record_cdata_handler);
2580 CharData_Init(&storage);
2581 XML_SetUserData(g_parser, &storage);
2582 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2583 == XML_STATUS_ERROR)
2584 xml_failure(g_parser);
2585 CharData_CheckXMLChars(&storage, XCS("DCDCDCDCDCDD"));
2586
2587 /* Again, without the defaulting */
2588 XML_ParserReset(g_parser, NULL);
2589 XML_SetDefaultHandler(g_parser, record_default_handler);
2590 XML_SetCharacterDataHandler(g_parser, record_cdata_nodefault_handler);
2591 CharData_Init(&storage);
2592 XML_SetUserData(g_parser, &storage);
2593 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2594 == XML_STATUS_ERROR)
2595 xml_failure(g_parser);
2596 CharData_CheckXMLChars(&storage, XCS("DcccccD"));
2597
2598 /* Now with an internal entity to complicate matters */
2599 XML_ParserReset(g_parser, NULL);
2600 XML_SetDefaultHandler(g_parser, record_default_handler);
2601 XML_SetCharacterDataHandler(g_parser, record_cdata_handler);
2602 CharData_Init(&storage);
2603 XML_SetUserData(g_parser, &storage);
2604 if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text),
2605 XML_TRUE)
2606 == XML_STATUS_ERROR)
2607 xml_failure(g_parser);
2608 /* The default handler suppresses the entity */
2609 CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDDD"));
2610
2611 /* Again, with a skip handler */
2612 XML_ParserReset(g_parser, NULL);
2613 XML_SetDefaultHandler(g_parser, record_default_handler);
2614 XML_SetCharacterDataHandler(g_parser, record_cdata_handler);
2615 XML_SetSkippedEntityHandler(g_parser, record_skip_handler);
2616 CharData_Init(&storage);
2617 XML_SetUserData(g_parser, &storage);
2618 if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text),
2619 XML_TRUE)
2620 == XML_STATUS_ERROR)
2621 xml_failure(g_parser);
2622 /* The default handler suppresses the entity */
2623 CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDeD"));
2624
2625 /* This time, allow the entity through */
2626 XML_ParserReset(g_parser, NULL);
2627 XML_SetDefaultHandlerExpand(g_parser, record_default_handler);
2628 XML_SetCharacterDataHandler(g_parser, record_cdata_handler);
2629 CharData_Init(&storage);
2630 XML_SetUserData(g_parser, &storage);
2631 if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text),
2632 XML_TRUE)
2633 == XML_STATUS_ERROR)
2634 xml_failure(g_parser);
2635 CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDCDD"));
2636
2637 /* Finally, without passing the cdata to the default handler */
2638 XML_ParserReset(g_parser, NULL);
2639 XML_SetDefaultHandlerExpand(g_parser, record_default_handler);
2640 XML_SetCharacterDataHandler(g_parser, record_cdata_nodefault_handler);
2641 CharData_Init(&storage);
2642 XML_SetUserData(g_parser, &storage);
2643 if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text),
2644 XML_TRUE)
2645 == XML_STATUS_ERROR)
2646 xml_failure(g_parser);
2647 CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDcD"));
2648 }
2649 END_TEST
2650
2651 /* Test DTD element parsing code paths */
START_TEST(test_dtd_elements)2652 START_TEST(test_dtd_elements) {
2653 const char *text = "<!DOCTYPE doc [\n"
2654 "<!ELEMENT doc (chapter)>\n"
2655 "<!ELEMENT chapter (#PCDATA)>\n"
2656 "]>\n"
2657 "<doc><chapter>Wombats are go</chapter></doc>";
2658
2659 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
2660 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2661 == XML_STATUS_ERROR)
2662 xml_failure(g_parser);
2663 }
2664 END_TEST
2665
2666 /* Test foreign DTD handling */
START_TEST(test_set_foreign_dtd)2667 START_TEST(test_set_foreign_dtd) {
2668 const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n";
2669 const char *text2 = "<doc>&entity;</doc>";
2670 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
2671
2672 /* Check hash salt is passed through too */
2673 XML_SetHashSalt(g_parser, 0x12345678);
2674 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2675 XML_SetUserData(g_parser, &test_data);
2676 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
2677 /* Add a default handler to exercise more code paths */
2678 XML_SetDefaultHandler(g_parser, dummy_default_handler);
2679 if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE)
2680 fail("Could not set foreign DTD");
2681 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
2682 == XML_STATUS_ERROR)
2683 xml_failure(g_parser);
2684
2685 /* Ensure that trying to set the DTD after parsing has started
2686 * is faulted, even if it's the same setting.
2687 */
2688 if (XML_UseForeignDTD(g_parser, XML_TRUE)
2689 != XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING)
2690 fail("Failed to reject late foreign DTD setting");
2691 /* Ditto for the hash salt */
2692 if (XML_SetHashSalt(g_parser, 0x23456789))
2693 fail("Failed to reject late hash salt change");
2694
2695 /* Now finish the parse */
2696 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
2697 == XML_STATUS_ERROR)
2698 xml_failure(g_parser);
2699 }
2700 END_TEST
2701
2702 /* Test foreign DTD handling with a failing NotStandalone handler */
START_TEST(test_foreign_dtd_not_standalone)2703 START_TEST(test_foreign_dtd_not_standalone) {
2704 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
2705 "<doc>&entity;</doc>";
2706 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
2707
2708 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2709 XML_SetUserData(g_parser, &test_data);
2710 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
2711 XML_SetNotStandaloneHandler(g_parser, reject_not_standalone_handler);
2712 if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE)
2713 fail("Could not set foreign DTD");
2714 expect_failure(text, XML_ERROR_NOT_STANDALONE,
2715 "NotStandalonehandler failed to reject");
2716 }
2717 END_TEST
2718
2719 /* Test invalid character in a foreign DTD is faulted */
START_TEST(test_invalid_foreign_dtd)2720 START_TEST(test_invalid_foreign_dtd) {
2721 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
2722 "<doc>&entity;</doc>";
2723 ExtFaults test_data
2724 = {"$", "Dollar not faulted", NULL, XML_ERROR_INVALID_TOKEN};
2725
2726 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2727 XML_SetUserData(g_parser, &test_data);
2728 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
2729 XML_UseForeignDTD(g_parser, XML_TRUE);
2730 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
2731 "Bad DTD should not have been accepted");
2732 }
2733 END_TEST
2734
2735 /* Test foreign DTD use with a doctype */
START_TEST(test_foreign_dtd_with_doctype)2736 START_TEST(test_foreign_dtd_with_doctype) {
2737 const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n"
2738 "<!DOCTYPE doc [<!ENTITY entity 'hello world'>]>\n";
2739 const char *text2 = "<doc>&entity;</doc>";
2740 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
2741
2742 /* Check hash salt is passed through too */
2743 XML_SetHashSalt(g_parser, 0x12345678);
2744 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2745 XML_SetUserData(g_parser, &test_data);
2746 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
2747 /* Add a default handler to exercise more code paths */
2748 XML_SetDefaultHandler(g_parser, dummy_default_handler);
2749 if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE)
2750 fail("Could not set foreign DTD");
2751 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
2752 == XML_STATUS_ERROR)
2753 xml_failure(g_parser);
2754
2755 /* Ensure that trying to set the DTD after parsing has started
2756 * is faulted, even if it's the same setting.
2757 */
2758 if (XML_UseForeignDTD(g_parser, XML_TRUE)
2759 != XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING)
2760 fail("Failed to reject late foreign DTD setting");
2761 /* Ditto for the hash salt */
2762 if (XML_SetHashSalt(g_parser, 0x23456789))
2763 fail("Failed to reject late hash salt change");
2764
2765 /* Now finish the parse */
2766 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
2767 == XML_STATUS_ERROR)
2768 xml_failure(g_parser);
2769 }
2770 END_TEST
2771
2772 /* Test XML_UseForeignDTD with no external subset present */
2773 static int XMLCALL
external_entity_null_loader(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)2774 external_entity_null_loader(XML_Parser parser, const XML_Char *context,
2775 const XML_Char *base, const XML_Char *systemId,
2776 const XML_Char *publicId) {
2777 UNUSED_P(parser);
2778 UNUSED_P(context);
2779 UNUSED_P(base);
2780 UNUSED_P(systemId);
2781 UNUSED_P(publicId);
2782 return XML_STATUS_OK;
2783 }
2784
START_TEST(test_foreign_dtd_without_external_subset)2785 START_TEST(test_foreign_dtd_without_external_subset) {
2786 const char *text = "<!DOCTYPE doc [<!ENTITY foo 'bar'>]>\n"
2787 "<doc>&foo;</doc>";
2788
2789 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2790 XML_SetUserData(g_parser, NULL);
2791 XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader);
2792 XML_UseForeignDTD(g_parser, XML_TRUE);
2793 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2794 == XML_STATUS_ERROR)
2795 xml_failure(g_parser);
2796 }
2797 END_TEST
2798
START_TEST(test_empty_foreign_dtd)2799 START_TEST(test_empty_foreign_dtd) {
2800 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
2801 "<doc>&entity;</doc>";
2802
2803 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2804 XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader);
2805 XML_UseForeignDTD(g_parser, XML_TRUE);
2806 expect_failure(text, XML_ERROR_UNDEFINED_ENTITY,
2807 "Undefined entity not faulted");
2808 }
2809 END_TEST
2810
2811 /* Test XML Base is set and unset appropriately */
START_TEST(test_set_base)2812 START_TEST(test_set_base) {
2813 const XML_Char *old_base;
2814 const XML_Char *new_base = XCS("/local/file/name.xml");
2815
2816 old_base = XML_GetBase(g_parser);
2817 if (XML_SetBase(g_parser, new_base) != XML_STATUS_OK)
2818 fail("Unable to set base");
2819 if (xcstrcmp(XML_GetBase(g_parser), new_base) != 0)
2820 fail("Base setting not correct");
2821 if (XML_SetBase(g_parser, NULL) != XML_STATUS_OK)
2822 fail("Unable to NULL base");
2823 if (XML_GetBase(g_parser) != NULL)
2824 fail("Base setting not nulled");
2825 XML_SetBase(g_parser, old_base);
2826 }
2827 END_TEST
2828
2829 /* Test attribute counts, indexing, etc */
2830 typedef struct attrInfo {
2831 const XML_Char *name;
2832 const XML_Char *value;
2833 } AttrInfo;
2834
2835 typedef struct elementInfo {
2836 const XML_Char *name;
2837 int attr_count;
2838 const XML_Char *id_name;
2839 AttrInfo *attributes;
2840 } ElementInfo;
2841
2842 static void XMLCALL
counting_start_element_handler(void * userData,const XML_Char * name,const XML_Char ** atts)2843 counting_start_element_handler(void *userData, const XML_Char *name,
2844 const XML_Char **atts) {
2845 ElementInfo *info = (ElementInfo *)userData;
2846 AttrInfo *attr;
2847 int count, id, i;
2848
2849 while (info->name != NULL) {
2850 if (! xcstrcmp(name, info->name))
2851 break;
2852 info++;
2853 }
2854 if (info->name == NULL)
2855 fail("Element not recognised");
2856 /* The attribute count is twice what you might expect. It is a
2857 * count of items in atts, an array which contains alternating
2858 * attribute names and attribute values. For the naive user this
2859 * is possibly a little unexpected, but it is what the
2860 * documentation in expat.h tells us to expect.
2861 */
2862 count = XML_GetSpecifiedAttributeCount(g_parser);
2863 if (info->attr_count * 2 != count) {
2864 fail("Not got expected attribute count");
2865 return;
2866 }
2867 id = XML_GetIdAttributeIndex(g_parser);
2868 if (id == -1 && info->id_name != NULL) {
2869 fail("ID not present");
2870 return;
2871 }
2872 if (id != -1 && xcstrcmp(atts[id], info->id_name)) {
2873 fail("ID does not have the correct name");
2874 return;
2875 }
2876 for (i = 0; i < info->attr_count; i++) {
2877 attr = info->attributes;
2878 while (attr->name != NULL) {
2879 if (! xcstrcmp(atts[0], attr->name))
2880 break;
2881 attr++;
2882 }
2883 if (attr->name == NULL) {
2884 fail("Attribute not recognised");
2885 return;
2886 }
2887 if (xcstrcmp(atts[1], attr->value)) {
2888 fail("Attribute has wrong value");
2889 return;
2890 }
2891 /* Remember, two entries in atts per attribute (see above) */
2892 atts += 2;
2893 }
2894 }
2895
START_TEST(test_attributes)2896 START_TEST(test_attributes) {
2897 const char *text = "<!DOCTYPE doc [\n"
2898 "<!ELEMENT doc (tag)>\n"
2899 "<!ATTLIST doc id ID #REQUIRED>\n"
2900 "]>"
2901 "<doc a='1' id='one' b='2'>"
2902 "<tag c='3'/>"
2903 "</doc>";
2904 AttrInfo doc_info[] = {{XCS("a"), XCS("1")},
2905 {XCS("b"), XCS("2")},
2906 {XCS("id"), XCS("one")},
2907 {NULL, NULL}};
2908 AttrInfo tag_info[] = {{XCS("c"), XCS("3")}, {NULL, NULL}};
2909 ElementInfo info[] = {{XCS("doc"), 3, XCS("id"), NULL},
2910 {XCS("tag"), 1, NULL, NULL},
2911 {NULL, 0, NULL, NULL}};
2912 info[0].attributes = doc_info;
2913 info[1].attributes = tag_info;
2914
2915 XML_SetStartElementHandler(g_parser, counting_start_element_handler);
2916 XML_SetUserData(g_parser, info);
2917 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2918 == XML_STATUS_ERROR)
2919 xml_failure(g_parser);
2920 }
2921 END_TEST
2922
2923 /* Test reset works correctly in the middle of processing an internal
2924 * entity. Exercises some obscure code in XML_ParserReset().
2925 */
START_TEST(test_reset_in_entity)2926 START_TEST(test_reset_in_entity) {
2927 const char *text = "<!DOCTYPE doc [\n"
2928 "<!ENTITY wombat 'wom'>\n"
2929 "<!ENTITY entity 'hi &wom; there'>\n"
2930 "]>\n"
2931 "<doc>&entity;</doc>";
2932 XML_ParsingStatus status;
2933
2934 resumable = XML_TRUE;
2935 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2936 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
2937 == XML_STATUS_ERROR)
2938 xml_failure(g_parser);
2939 XML_GetParsingStatus(g_parser, &status);
2940 if (status.parsing != XML_SUSPENDED)
2941 fail("Parsing status not SUSPENDED");
2942 XML_ParserReset(g_parser, NULL);
2943 XML_GetParsingStatus(g_parser, &status);
2944 if (status.parsing != XML_INITIALIZED)
2945 fail("Parsing status doesn't reset to INITIALIZED");
2946 }
2947 END_TEST
2948
2949 /* Test that resume correctly passes through parse errors */
START_TEST(test_resume_invalid_parse)2950 START_TEST(test_resume_invalid_parse) {
2951 const char *text = "<doc>Hello</doc"; /* Missing closing wedge */
2952
2953 resumable = XML_TRUE;
2954 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2955 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
2956 == XML_STATUS_ERROR)
2957 xml_failure(g_parser);
2958 if (XML_ResumeParser(g_parser) == XML_STATUS_OK)
2959 fail("Resumed invalid parse not faulted");
2960 if (XML_GetErrorCode(g_parser) != XML_ERROR_UNCLOSED_TOKEN)
2961 fail("Invalid parse not correctly faulted");
2962 }
2963 END_TEST
2964
2965 /* Test that re-suspended parses are correctly passed through */
START_TEST(test_resume_resuspended)2966 START_TEST(test_resume_resuspended) {
2967 const char *text = "<doc>Hello<meep/>world</doc>";
2968
2969 resumable = XML_TRUE;
2970 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2971 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
2972 == XML_STATUS_ERROR)
2973 xml_failure(g_parser);
2974 resumable = XML_TRUE;
2975 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2976 if (XML_ResumeParser(g_parser) != XML_STATUS_SUSPENDED)
2977 fail("Resumption not suspended");
2978 /* This one should succeed and finish up */
2979 if (XML_ResumeParser(g_parser) != XML_STATUS_OK)
2980 xml_failure(g_parser);
2981 }
2982 END_TEST
2983
2984 /* Test that CDATA shows up correctly through a default handler */
START_TEST(test_cdata_default)2985 START_TEST(test_cdata_default) {
2986 const char *text = "<doc><![CDATA[Hello\nworld]]></doc>";
2987 const XML_Char *expected = XCS("<doc><![CDATA[Hello\nworld]]></doc>");
2988 CharData storage;
2989
2990 CharData_Init(&storage);
2991 XML_SetUserData(g_parser, &storage);
2992 XML_SetDefaultHandler(g_parser, accumulate_characters);
2993
2994 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2995 == XML_STATUS_ERROR)
2996 xml_failure(g_parser);
2997 CharData_CheckXMLChars(&storage, expected);
2998 }
2999 END_TEST
3000
3001 /* Test resetting a subordinate parser does exactly nothing */
3002 static int XMLCALL
external_entity_resetter(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3003 external_entity_resetter(XML_Parser parser, const XML_Char *context,
3004 const XML_Char *base, const XML_Char *systemId,
3005 const XML_Char *publicId) {
3006 const char *text = "<!ELEMENT doc (#PCDATA)*>";
3007 XML_Parser ext_parser;
3008 XML_ParsingStatus status;
3009
3010 UNUSED_P(base);
3011 UNUSED_P(systemId);
3012 UNUSED_P(publicId);
3013 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3014 if (ext_parser == NULL)
3015 fail("Could not create external entity parser");
3016 XML_GetParsingStatus(ext_parser, &status);
3017 if (status.parsing != XML_INITIALIZED) {
3018 fail("Parsing status is not INITIALIZED");
3019 return XML_STATUS_ERROR;
3020 }
3021 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3022 == XML_STATUS_ERROR) {
3023 xml_failure(parser);
3024 return XML_STATUS_ERROR;
3025 }
3026 XML_GetParsingStatus(ext_parser, &status);
3027 if (status.parsing != XML_FINISHED) {
3028 fail("Parsing status is not FINISHED");
3029 return XML_STATUS_ERROR;
3030 }
3031 /* Check we can't parse here */
3032 if (XML_Parse(ext_parser, text, (int)strlen(text), XML_TRUE)
3033 != XML_STATUS_ERROR)
3034 fail("Parsing when finished not faulted");
3035 if (XML_GetErrorCode(ext_parser) != XML_ERROR_FINISHED)
3036 fail("Parsing when finished faulted with wrong code");
3037 XML_ParserReset(ext_parser, NULL);
3038 XML_GetParsingStatus(ext_parser, &status);
3039 if (status.parsing != XML_FINISHED) {
3040 fail("Parsing status not still FINISHED");
3041 return XML_STATUS_ERROR;
3042 }
3043 XML_ParserFree(ext_parser);
3044 return XML_STATUS_OK;
3045 }
3046
START_TEST(test_subordinate_reset)3047 START_TEST(test_subordinate_reset) {
3048 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
3049 "<!DOCTYPE doc SYSTEM 'foo'>\n"
3050 "<doc>&entity;</doc>";
3051
3052 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3053 XML_SetExternalEntityRefHandler(g_parser, external_entity_resetter);
3054 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3055 == XML_STATUS_ERROR)
3056 xml_failure(g_parser);
3057 }
3058 END_TEST
3059
3060 /* Test suspending a subordinate parser */
3061
3062 static void XMLCALL
entity_suspending_decl_handler(void * userData,const XML_Char * name,XML_Content * model)3063 entity_suspending_decl_handler(void *userData, const XML_Char *name,
3064 XML_Content *model) {
3065 XML_Parser ext_parser = (XML_Parser)userData;
3066
3067 UNUSED_P(name);
3068 if (XML_StopParser(ext_parser, XML_TRUE) != XML_STATUS_ERROR)
3069 fail("Attempting to suspend a subordinate parser not faulted");
3070 if (XML_GetErrorCode(ext_parser) != XML_ERROR_SUSPEND_PE)
3071 fail("Suspending subordinate parser get wrong code");
3072 XML_SetElementDeclHandler(ext_parser, NULL);
3073 XML_FreeContentModel(g_parser, model);
3074 }
3075
3076 static int XMLCALL
external_entity_suspender(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3077 external_entity_suspender(XML_Parser parser, const XML_Char *context,
3078 const XML_Char *base, const XML_Char *systemId,
3079 const XML_Char *publicId) {
3080 const char *text = "<!ELEMENT doc (#PCDATA)*>";
3081 XML_Parser ext_parser;
3082
3083 UNUSED_P(base);
3084 UNUSED_P(systemId);
3085 UNUSED_P(publicId);
3086 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3087 if (ext_parser == NULL)
3088 fail("Could not create external entity parser");
3089 XML_SetElementDeclHandler(ext_parser, entity_suspending_decl_handler);
3090 XML_SetUserData(ext_parser, ext_parser);
3091 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3092 == XML_STATUS_ERROR) {
3093 xml_failure(ext_parser);
3094 return XML_STATUS_ERROR;
3095 }
3096 XML_ParserFree(ext_parser);
3097 return XML_STATUS_OK;
3098 }
3099
START_TEST(test_subordinate_suspend)3100 START_TEST(test_subordinate_suspend) {
3101 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
3102 "<!DOCTYPE doc SYSTEM 'foo'>\n"
3103 "<doc>&entity;</doc>";
3104
3105 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3106 XML_SetExternalEntityRefHandler(g_parser, external_entity_suspender);
3107 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3108 == XML_STATUS_ERROR)
3109 xml_failure(g_parser);
3110 }
3111 END_TEST
3112
3113 /* Test suspending a subordinate parser from an XML declaration */
3114 /* Increases code coverage of the tests */
3115 static void XMLCALL
entity_suspending_xdecl_handler(void * userData,const XML_Char * version,const XML_Char * encoding,int standalone)3116 entity_suspending_xdecl_handler(void *userData, const XML_Char *version,
3117 const XML_Char *encoding, int standalone) {
3118 XML_Parser ext_parser = (XML_Parser)userData;
3119
3120 UNUSED_P(version);
3121 UNUSED_P(encoding);
3122 UNUSED_P(standalone);
3123 XML_StopParser(ext_parser, resumable);
3124 XML_SetXmlDeclHandler(ext_parser, NULL);
3125 }
3126
3127 static int XMLCALL
external_entity_suspend_xmldecl(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3128 external_entity_suspend_xmldecl(XML_Parser parser, const XML_Char *context,
3129 const XML_Char *base, const XML_Char *systemId,
3130 const XML_Char *publicId) {
3131 const char *text = "<?xml version='1.0' encoding='us-ascii'?>";
3132 XML_Parser ext_parser;
3133 XML_ParsingStatus status;
3134 enum XML_Status rc;
3135
3136 UNUSED_P(base);
3137 UNUSED_P(systemId);
3138 UNUSED_P(publicId);
3139 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3140 if (ext_parser == NULL)
3141 fail("Could not create external entity parser");
3142 XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
3143 XML_SetUserData(ext_parser, ext_parser);
3144 rc = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
3145 XML_GetParsingStatus(ext_parser, &status);
3146 if (resumable) {
3147 if (rc == XML_STATUS_ERROR)
3148 xml_failure(ext_parser);
3149 if (status.parsing != XML_SUSPENDED)
3150 fail("Ext Parsing status not SUSPENDED");
3151 } else {
3152 if (rc != XML_STATUS_ERROR)
3153 fail("Ext parsing not aborted");
3154 if (XML_GetErrorCode(ext_parser) != XML_ERROR_ABORTED)
3155 xml_failure(ext_parser);
3156 if (status.parsing != XML_FINISHED)
3157 fail("Ext Parsing status not FINISHED");
3158 }
3159
3160 XML_ParserFree(ext_parser);
3161 return XML_STATUS_OK;
3162 }
3163
START_TEST(test_subordinate_xdecl_suspend)3164 START_TEST(test_subordinate_xdecl_suspend) {
3165 const char *text
3166 = "<!DOCTYPE doc [\n"
3167 " <!ENTITY entity SYSTEM 'http://example.org/dummy.ent'>\n"
3168 "]>\n"
3169 "<doc>&entity;</doc>";
3170
3171 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3172 XML_SetExternalEntityRefHandler(g_parser, external_entity_suspend_xmldecl);
3173 resumable = XML_TRUE;
3174 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3175 == XML_STATUS_ERROR)
3176 xml_failure(g_parser);
3177 }
3178 END_TEST
3179
START_TEST(test_subordinate_xdecl_abort)3180 START_TEST(test_subordinate_xdecl_abort) {
3181 const char *text
3182 = "<!DOCTYPE doc [\n"
3183 " <!ENTITY entity SYSTEM 'http://example.org/dummy.ent'>\n"
3184 "]>\n"
3185 "<doc>&entity;</doc>";
3186
3187 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3188 XML_SetExternalEntityRefHandler(g_parser, external_entity_suspend_xmldecl);
3189 resumable = XML_FALSE;
3190 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3191 == XML_STATUS_ERROR)
3192 xml_failure(g_parser);
3193 }
3194 END_TEST
3195
3196 /* Test external entity fault handling with suspension */
3197 static int XMLCALL
external_entity_suspending_faulter(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3198 external_entity_suspending_faulter(XML_Parser parser, const XML_Char *context,
3199 const XML_Char *base,
3200 const XML_Char *systemId,
3201 const XML_Char *publicId) {
3202 XML_Parser ext_parser;
3203 ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser);
3204 void *buffer;
3205 int parse_len = (int)strlen(fault->parse_text);
3206
3207 UNUSED_P(base);
3208 UNUSED_P(systemId);
3209 UNUSED_P(publicId);
3210 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3211 if (ext_parser == NULL)
3212 fail("Could not create external entity parser");
3213 XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
3214 XML_SetUserData(ext_parser, ext_parser);
3215 resumable = XML_TRUE;
3216 buffer = XML_GetBuffer(ext_parser, parse_len);
3217 if (buffer == NULL)
3218 fail("Could not allocate parse buffer");
3219 assert(buffer != NULL);
3220 memcpy(buffer, fault->parse_text, parse_len);
3221 if (XML_ParseBuffer(ext_parser, parse_len, XML_FALSE) != XML_STATUS_SUSPENDED)
3222 fail("XML declaration did not suspend");
3223 if (XML_ResumeParser(ext_parser) != XML_STATUS_OK)
3224 xml_failure(ext_parser);
3225 if (XML_ParseBuffer(ext_parser, 0, XML_TRUE) != XML_STATUS_ERROR)
3226 fail(fault->fail_text);
3227 if (XML_GetErrorCode(ext_parser) != fault->error)
3228 xml_failure(ext_parser);
3229
3230 XML_ParserFree(ext_parser);
3231 return XML_STATUS_ERROR;
3232 }
3233
START_TEST(test_ext_entity_invalid_suspended_parse)3234 START_TEST(test_ext_entity_invalid_suspended_parse) {
3235 const char *text = "<!DOCTYPE doc [\n"
3236 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
3237 "]>\n"
3238 "<doc>&en;</doc>";
3239 ExtFaults faults[]
3240 = {{"<?xml version='1.0' encoding='us-ascii'?><",
3241 "Incomplete element declaration not faulted", NULL,
3242 XML_ERROR_UNCLOSED_TOKEN},
3243 {/* First two bytes of a three-byte char */
3244 "<?xml version='1.0' encoding='utf-8'?>\xe2\x82",
3245 "Incomplete character not faulted", NULL, XML_ERROR_PARTIAL_CHAR},
3246 {NULL, NULL, NULL, XML_ERROR_NONE}};
3247 ExtFaults *fault;
3248
3249 for (fault = &faults[0]; fault->parse_text != NULL; fault++) {
3250 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3251 XML_SetExternalEntityRefHandler(g_parser,
3252 external_entity_suspending_faulter);
3253 XML_SetUserData(g_parser, fault);
3254 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
3255 "Parser did not report external entity error");
3256 XML_ParserReset(g_parser, NULL);
3257 }
3258 }
3259 END_TEST
3260
3261 /* Test setting an explicit encoding */
START_TEST(test_explicit_encoding)3262 START_TEST(test_explicit_encoding) {
3263 const char *text1 = "<doc>Hello ";
3264 const char *text2 = " World</doc>";
3265
3266 /* Just check that we can set the encoding to NULL before starting */
3267 if (XML_SetEncoding(g_parser, NULL) != XML_STATUS_OK)
3268 fail("Failed to initialise encoding to NULL");
3269 /* Say we are UTF-8 */
3270 if (XML_SetEncoding(g_parser, XCS("utf-8")) != XML_STATUS_OK)
3271 fail("Failed to set explicit encoding");
3272 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
3273 == XML_STATUS_ERROR)
3274 xml_failure(g_parser);
3275 /* Try to switch encodings mid-parse */
3276 if (XML_SetEncoding(g_parser, XCS("us-ascii")) != XML_STATUS_ERROR)
3277 fail("Allowed encoding change");
3278 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
3279 == XML_STATUS_ERROR)
3280 xml_failure(g_parser);
3281 /* Try now the parse is over */
3282 if (XML_SetEncoding(g_parser, NULL) != XML_STATUS_OK)
3283 fail("Failed to unset encoding");
3284 }
3285 END_TEST
3286
3287 /* Test handling of trailing CR (rather than newline) */
3288 static void XMLCALL
cr_cdata_handler(void * userData,const XML_Char * s,int len)3289 cr_cdata_handler(void *userData, const XML_Char *s, int len) {
3290 int *pfound = (int *)userData;
3291
3292 /* Internal processing turns the CR into a newline for the
3293 * character data handler, but not for the default handler
3294 */
3295 if (len == 1 && (*s == XCS('\n') || *s == XCS('\r')))
3296 *pfound = 1;
3297 }
3298
START_TEST(test_trailing_cr)3299 START_TEST(test_trailing_cr) {
3300 const char *text = "<doc>\r";
3301 int found_cr;
3302
3303 /* Try with a character handler, for code coverage */
3304 XML_SetCharacterDataHandler(g_parser, cr_cdata_handler);
3305 XML_SetUserData(g_parser, &found_cr);
3306 found_cr = 0;
3307 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3308 == XML_STATUS_OK)
3309 fail("Failed to fault unclosed doc");
3310 if (found_cr == 0)
3311 fail("Did not catch the carriage return");
3312 XML_ParserReset(g_parser, NULL);
3313
3314 /* Now with a default handler instead */
3315 XML_SetDefaultHandler(g_parser, cr_cdata_handler);
3316 XML_SetUserData(g_parser, &found_cr);
3317 found_cr = 0;
3318 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3319 == XML_STATUS_OK)
3320 fail("Failed to fault unclosed doc");
3321 if (found_cr == 0)
3322 fail("Did not catch default carriage return");
3323 }
3324 END_TEST
3325
3326 /* Test trailing CR in an external entity parse */
3327 static int XMLCALL
external_entity_cr_catcher(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3328 external_entity_cr_catcher(XML_Parser parser, const XML_Char *context,
3329 const XML_Char *base, const XML_Char *systemId,
3330 const XML_Char *publicId) {
3331 const char *text = "\r";
3332 XML_Parser ext_parser;
3333
3334 UNUSED_P(base);
3335 UNUSED_P(systemId);
3336 UNUSED_P(publicId);
3337 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3338 if (ext_parser == NULL)
3339 fail("Could not create external entity parser");
3340 XML_SetCharacterDataHandler(ext_parser, cr_cdata_handler);
3341 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3342 == XML_STATUS_ERROR)
3343 xml_failure(ext_parser);
3344 XML_ParserFree(ext_parser);
3345 return XML_STATUS_OK;
3346 }
3347
3348 static int XMLCALL
external_entity_bad_cr_catcher(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3349 external_entity_bad_cr_catcher(XML_Parser parser, const XML_Char *context,
3350 const XML_Char *base, const XML_Char *systemId,
3351 const XML_Char *publicId) {
3352 const char *text = "<tag>\r";
3353 XML_Parser ext_parser;
3354
3355 UNUSED_P(base);
3356 UNUSED_P(systemId);
3357 UNUSED_P(publicId);
3358 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3359 if (ext_parser == NULL)
3360 fail("Could not create external entity parser");
3361 XML_SetCharacterDataHandler(ext_parser, cr_cdata_handler);
3362 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3363 == XML_STATUS_OK)
3364 fail("Async entity error not caught");
3365 if (XML_GetErrorCode(ext_parser) != XML_ERROR_ASYNC_ENTITY)
3366 xml_failure(ext_parser);
3367 XML_ParserFree(ext_parser);
3368 return XML_STATUS_OK;
3369 }
3370
START_TEST(test_ext_entity_trailing_cr)3371 START_TEST(test_ext_entity_trailing_cr) {
3372 const char *text = "<!DOCTYPE doc [\n"
3373 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
3374 "]>\n"
3375 "<doc>&en;</doc>";
3376 int found_cr;
3377
3378 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3379 XML_SetExternalEntityRefHandler(g_parser, external_entity_cr_catcher);
3380 XML_SetUserData(g_parser, &found_cr);
3381 found_cr = 0;
3382 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3383 != XML_STATUS_OK)
3384 xml_failure(g_parser);
3385 if (found_cr == 0)
3386 fail("No carriage return found");
3387 XML_ParserReset(g_parser, NULL);
3388
3389 /* Try again with a different trailing CR */
3390 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3391 XML_SetExternalEntityRefHandler(g_parser, external_entity_bad_cr_catcher);
3392 XML_SetUserData(g_parser, &found_cr);
3393 found_cr = 0;
3394 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3395 != XML_STATUS_OK)
3396 xml_failure(g_parser);
3397 if (found_cr == 0)
3398 fail("No carriage return found");
3399 }
3400 END_TEST
3401
3402 /* Test handling of trailing square bracket */
3403 static void XMLCALL
rsqb_handler(void * userData,const XML_Char * s,int len)3404 rsqb_handler(void *userData, const XML_Char *s, int len) {
3405 int *pfound = (int *)userData;
3406
3407 if (len == 1 && *s == XCS(']'))
3408 *pfound = 1;
3409 }
3410
START_TEST(test_trailing_rsqb)3411 START_TEST(test_trailing_rsqb) {
3412 const char *text8 = "<doc>]";
3413 const char text16[] = "\xFF\xFE<\000d\000o\000c\000>\000]\000";
3414 int found_rsqb;
3415 int text8_len = (int)strlen(text8);
3416
3417 XML_SetCharacterDataHandler(g_parser, rsqb_handler);
3418 XML_SetUserData(g_parser, &found_rsqb);
3419 found_rsqb = 0;
3420 if (_XML_Parse_SINGLE_BYTES(g_parser, text8, text8_len, XML_TRUE)
3421 == XML_STATUS_OK)
3422 fail("Failed to fault unclosed doc");
3423 if (found_rsqb == 0)
3424 fail("Did not catch the right square bracket");
3425
3426 /* Try again with a different encoding */
3427 XML_ParserReset(g_parser, NULL);
3428 XML_SetCharacterDataHandler(g_parser, rsqb_handler);
3429 XML_SetUserData(g_parser, &found_rsqb);
3430 found_rsqb = 0;
3431 if (_XML_Parse_SINGLE_BYTES(g_parser, text16, (int)sizeof(text16) - 1,
3432 XML_TRUE)
3433 == XML_STATUS_OK)
3434 fail("Failed to fault unclosed doc");
3435 if (found_rsqb == 0)
3436 fail("Did not catch the right square bracket");
3437
3438 /* And finally with a default handler */
3439 XML_ParserReset(g_parser, NULL);
3440 XML_SetDefaultHandler(g_parser, rsqb_handler);
3441 XML_SetUserData(g_parser, &found_rsqb);
3442 found_rsqb = 0;
3443 if (_XML_Parse_SINGLE_BYTES(g_parser, text16, (int)sizeof(text16) - 1,
3444 XML_TRUE)
3445 == XML_STATUS_OK)
3446 fail("Failed to fault unclosed doc");
3447 if (found_rsqb == 0)
3448 fail("Did not catch the right square bracket");
3449 }
3450 END_TEST
3451
3452 /* Test trailing right square bracket in an external entity parse */
3453 static int XMLCALL
external_entity_rsqb_catcher(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3454 external_entity_rsqb_catcher(XML_Parser parser, const XML_Char *context,
3455 const XML_Char *base, const XML_Char *systemId,
3456 const XML_Char *publicId) {
3457 const char *text = "<tag>]";
3458 XML_Parser ext_parser;
3459
3460 UNUSED_P(base);
3461 UNUSED_P(systemId);
3462 UNUSED_P(publicId);
3463 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3464 if (ext_parser == NULL)
3465 fail("Could not create external entity parser");
3466 XML_SetCharacterDataHandler(ext_parser, rsqb_handler);
3467 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3468 != XML_STATUS_ERROR)
3469 fail("Async entity error not caught");
3470 if (XML_GetErrorCode(ext_parser) != XML_ERROR_ASYNC_ENTITY)
3471 xml_failure(ext_parser);
3472 XML_ParserFree(ext_parser);
3473 return XML_STATUS_OK;
3474 }
3475
START_TEST(test_ext_entity_trailing_rsqb)3476 START_TEST(test_ext_entity_trailing_rsqb) {
3477 const char *text = "<!DOCTYPE doc [\n"
3478 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
3479 "]>\n"
3480 "<doc>&en;</doc>";
3481 int found_rsqb;
3482
3483 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3484 XML_SetExternalEntityRefHandler(g_parser, external_entity_rsqb_catcher);
3485 XML_SetUserData(g_parser, &found_rsqb);
3486 found_rsqb = 0;
3487 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3488 != XML_STATUS_OK)
3489 xml_failure(g_parser);
3490 if (found_rsqb == 0)
3491 fail("No right square bracket found");
3492 }
3493 END_TEST
3494
3495 /* Test CDATA handling in an external entity */
3496 static int XMLCALL
external_entity_good_cdata_ascii(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3497 external_entity_good_cdata_ascii(XML_Parser parser, const XML_Char *context,
3498 const XML_Char *base, const XML_Char *systemId,
3499 const XML_Char *publicId) {
3500 const char *text = "<a><![CDATA[<greeting>Hello, world!</greeting>]]></a>";
3501 const XML_Char *expected = XCS("<greeting>Hello, world!</greeting>");
3502 CharData storage;
3503 XML_Parser ext_parser;
3504
3505 UNUSED_P(base);
3506 UNUSED_P(systemId);
3507 UNUSED_P(publicId);
3508 CharData_Init(&storage);
3509 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3510 if (ext_parser == NULL)
3511 fail("Could not create external entity parser");
3512 XML_SetUserData(ext_parser, &storage);
3513 XML_SetCharacterDataHandler(ext_parser, accumulate_characters);
3514
3515 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3516 == XML_STATUS_ERROR)
3517 xml_failure(ext_parser);
3518 CharData_CheckXMLChars(&storage, expected);
3519
3520 XML_ParserFree(ext_parser);
3521 return XML_STATUS_OK;
3522 }
3523
START_TEST(test_ext_entity_good_cdata)3524 START_TEST(test_ext_entity_good_cdata) {
3525 const char *text = "<!DOCTYPE doc [\n"
3526 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
3527 "]>\n"
3528 "<doc>&en;</doc>";
3529
3530 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3531 XML_SetExternalEntityRefHandler(g_parser, external_entity_good_cdata_ascii);
3532 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3533 != XML_STATUS_OK)
3534 xml_failure(g_parser);
3535 }
3536 END_TEST
3537
3538 /* Test user parameter settings */
3539 /* Variable holding the expected handler userData */
3540 static void *handler_data = NULL;
3541 /* Count of the number of times the comment handler has been invoked */
3542 static int comment_count = 0;
3543 /* Count of the number of skipped entities */
3544 static int skip_count = 0;
3545 /* Count of the number of times the XML declaration handler is invoked */
3546 static int xdecl_count = 0;
3547
3548 static void XMLCALL
xml_decl_handler(void * userData,const XML_Char * version,const XML_Char * encoding,int standalone)3549 xml_decl_handler(void *userData, const XML_Char *version,
3550 const XML_Char *encoding, int standalone) {
3551 UNUSED_P(version);
3552 UNUSED_P(encoding);
3553 if (userData != handler_data)
3554 fail("User data (xml decl) not correctly set");
3555 if (standalone != -1)
3556 fail("Standalone not flagged as not present in XML decl");
3557 xdecl_count++;
3558 }
3559
3560 static void XMLCALL
param_check_skip_handler(void * userData,const XML_Char * entityName,int is_parameter_entity)3561 param_check_skip_handler(void *userData, const XML_Char *entityName,
3562 int is_parameter_entity) {
3563 UNUSED_P(entityName);
3564 UNUSED_P(is_parameter_entity);
3565 if (userData != handler_data)
3566 fail("User data (skip) not correctly set");
3567 skip_count++;
3568 }
3569
3570 static void XMLCALL
data_check_comment_handler(void * userData,const XML_Char * data)3571 data_check_comment_handler(void *userData, const XML_Char *data) {
3572 UNUSED_P(data);
3573 /* Check that the userData passed through is what we expect */
3574 if (userData != handler_data)
3575 fail("User data (parser) not correctly set");
3576 /* Check that the user data in the parser is appropriate */
3577 if (XML_GetUserData(userData) != (void *)1)
3578 fail("User data in parser not correctly set");
3579 comment_count++;
3580 }
3581
3582 static int XMLCALL
external_entity_param_checker(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3583 external_entity_param_checker(XML_Parser parser, const XML_Char *context,
3584 const XML_Char *base, const XML_Char *systemId,
3585 const XML_Char *publicId) {
3586 const char *text = "<!-- Subordinate parser -->\n"
3587 "<!ELEMENT doc (#PCDATA)*>";
3588 XML_Parser ext_parser;
3589
3590 UNUSED_P(base);
3591 UNUSED_P(systemId);
3592 UNUSED_P(publicId);
3593 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3594 if (ext_parser == NULL)
3595 fail("Could not create external entity parser");
3596 handler_data = ext_parser;
3597 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3598 == XML_STATUS_ERROR) {
3599 xml_failure(parser);
3600 return XML_STATUS_ERROR;
3601 }
3602 handler_data = parser;
3603 XML_ParserFree(ext_parser);
3604 return XML_STATUS_OK;
3605 }
3606
START_TEST(test_user_parameters)3607 START_TEST(test_user_parameters) {
3608 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
3609 "<!-- Primary parse -->\n"
3610 "<!DOCTYPE doc SYSTEM 'foo'>\n"
3611 "<doc>&entity;";
3612 const char *epilog = "<!-- Back to primary parser -->\n"
3613 "</doc>";
3614
3615 comment_count = 0;
3616 skip_count = 0;
3617 xdecl_count = 0;
3618 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3619 XML_SetXmlDeclHandler(g_parser, xml_decl_handler);
3620 XML_SetExternalEntityRefHandler(g_parser, external_entity_param_checker);
3621 XML_SetCommentHandler(g_parser, data_check_comment_handler);
3622 XML_SetSkippedEntityHandler(g_parser, param_check_skip_handler);
3623 XML_UseParserAsHandlerArg(g_parser);
3624 XML_SetUserData(g_parser, (void *)1);
3625 handler_data = g_parser;
3626 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
3627 == XML_STATUS_ERROR)
3628 xml_failure(g_parser);
3629 if (comment_count != 2)
3630 fail("Comment handler not invoked enough times");
3631 /* Ensure we can't change policy mid-parse */
3632 if (XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_NEVER))
3633 fail("Changed param entity parsing policy while parsing");
3634 if (_XML_Parse_SINGLE_BYTES(g_parser, epilog, (int)strlen(epilog), XML_TRUE)
3635 == XML_STATUS_ERROR)
3636 xml_failure(g_parser);
3637 if (comment_count != 3)
3638 fail("Comment handler not invoked enough times");
3639 if (skip_count != 1)
3640 fail("Skip handler not invoked enough times");
3641 if (xdecl_count != 1)
3642 fail("XML declaration handler not invoked");
3643 }
3644 END_TEST
3645
3646 /* Test that an explicit external entity handler argument replaces
3647 * the parser as the first argument.
3648 *
3649 * We do not call the first parameter to the external entity handler
3650 * 'parser' for once, since the first time the handler is called it
3651 * will actually be a text string. We need to be able to access the
3652 * global 'parser' variable to create our external entity parser from,
3653 * since there are code paths we need to ensure get executed.
3654 */
3655 static int XMLCALL
external_entity_ref_param_checker(XML_Parser parameter,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3656 external_entity_ref_param_checker(XML_Parser parameter, const XML_Char *context,
3657 const XML_Char *base,
3658 const XML_Char *systemId,
3659 const XML_Char *publicId) {
3660 const char *text = "<!ELEMENT doc (#PCDATA)*>";
3661 XML_Parser ext_parser;
3662
3663 UNUSED_P(base);
3664 UNUSED_P(systemId);
3665 UNUSED_P(publicId);
3666 if ((void *)parameter != handler_data)
3667 fail("External entity ref handler parameter not correct");
3668
3669 /* Here we use the global 'parser' variable */
3670 ext_parser = XML_ExternalEntityParserCreate(g_parser, context, NULL);
3671 if (ext_parser == NULL)
3672 fail("Could not create external entity parser");
3673 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3674 == XML_STATUS_ERROR)
3675 xml_failure(ext_parser);
3676
3677 XML_ParserFree(ext_parser);
3678 return XML_STATUS_OK;
3679 }
3680
START_TEST(test_ext_entity_ref_parameter)3681 START_TEST(test_ext_entity_ref_parameter) {
3682 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
3683 "<!DOCTYPE doc SYSTEM 'foo'>\n"
3684 "<doc>&entity;</doc>";
3685
3686 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3687 XML_SetExternalEntityRefHandler(g_parser, external_entity_ref_param_checker);
3688 /* Set a handler arg that is not NULL and not parser (which is
3689 * what NULL would cause to be passed.
3690 */
3691 XML_SetExternalEntityRefHandlerArg(g_parser, (void *)text);
3692 handler_data = (void *)text;
3693 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3694 == XML_STATUS_ERROR)
3695 xml_failure(g_parser);
3696
3697 /* Now try again with unset args */
3698 XML_ParserReset(g_parser, NULL);
3699 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3700 XML_SetExternalEntityRefHandler(g_parser, external_entity_ref_param_checker);
3701 XML_SetExternalEntityRefHandlerArg(g_parser, NULL);
3702 handler_data = (void *)g_parser;
3703 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3704 == XML_STATUS_ERROR)
3705 xml_failure(g_parser);
3706 }
3707 END_TEST
3708
3709 /* Test the parsing of an empty string */
START_TEST(test_empty_parse)3710 START_TEST(test_empty_parse) {
3711 const char *text = "<doc></doc>";
3712 const char *partial = "<doc>";
3713
3714 if (XML_Parse(g_parser, NULL, 0, XML_FALSE) == XML_STATUS_ERROR)
3715 fail("Parsing empty string faulted");
3716 if (XML_Parse(g_parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR)
3717 fail("Parsing final empty string not faulted");
3718 if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_ELEMENTS)
3719 fail("Parsing final empty string faulted for wrong reason");
3720
3721 /* Now try with valid text before the empty end */
3722 XML_ParserReset(g_parser, NULL);
3723 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
3724 == XML_STATUS_ERROR)
3725 xml_failure(g_parser);
3726 if (XML_Parse(g_parser, NULL, 0, XML_TRUE) == XML_STATUS_ERROR)
3727 fail("Parsing final empty string faulted");
3728
3729 /* Now try with invalid text before the empty end */
3730 XML_ParserReset(g_parser, NULL);
3731 if (_XML_Parse_SINGLE_BYTES(g_parser, partial, (int)strlen(partial),
3732 XML_FALSE)
3733 == XML_STATUS_ERROR)
3734 xml_failure(g_parser);
3735 if (XML_Parse(g_parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR)
3736 fail("Parsing final incomplete empty string not faulted");
3737 }
3738 END_TEST
3739
3740 /* Test odd corners of the XML_GetBuffer interface */
3741 static enum XML_Status
get_feature(enum XML_FeatureEnum feature_id,long * presult)3742 get_feature(enum XML_FeatureEnum feature_id, long *presult) {
3743 const XML_Feature *feature = XML_GetFeatureList();
3744
3745 if (feature == NULL)
3746 return XML_STATUS_ERROR;
3747 for (; feature->feature != XML_FEATURE_END; feature++) {
3748 if (feature->feature == feature_id) {
3749 *presult = feature->value;
3750 return XML_STATUS_OK;
3751 }
3752 }
3753 return XML_STATUS_ERROR;
3754 }
3755
3756 /* Having an element name longer than 1024 characters exercises some
3757 * of the pool allocation code in the parser that otherwise does not
3758 * get executed. The count at the end of the line is the number of
3759 * characters (bytes) in the element name by that point.x
3760 */
3761 static const char *get_buffer_test_text
3762 = "<documentwitharidiculouslylongelementnametotease" /* 0x030 */
3763 "aparticularcorneroftheallocationinXML_GetBuffers" /* 0x060 */
3764 "othatwecanimprovethecoverageyetagain012345678901" /* 0x090 */
3765 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x0c0 */
3766 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x0f0 */
3767 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x120 */
3768 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x150 */
3769 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x180 */
3770 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x1b0 */
3771 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x1e0 */
3772 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x210 */
3773 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x240 */
3774 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x270 */
3775 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x2a0 */
3776 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x2d0 */
3777 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x300 */
3778 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x330 */
3779 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x360 */
3780 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x390 */
3781 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x3c0 */
3782 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x3f0 */
3783 "123456789abcdef0123456789abcdef0123456789>\n<ef0"; /* 0x420 */
3784
3785 /* Test odd corners of the XML_GetBuffer interface */
START_TEST(test_get_buffer_1)3786 START_TEST(test_get_buffer_1) {
3787 const char *text = get_buffer_test_text;
3788 void *buffer;
3789 long context_bytes;
3790
3791 /* Attempt to allocate a negative length buffer */
3792 if (XML_GetBuffer(g_parser, -12) != NULL)
3793 fail("Negative length buffer not failed");
3794
3795 /* Now get a small buffer and extend it past valid length */
3796 buffer = XML_GetBuffer(g_parser, 1536);
3797 if (buffer == NULL)
3798 fail("1.5K buffer failed");
3799 assert(buffer != NULL);
3800 memcpy(buffer, text, strlen(text));
3801 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE)
3802 == XML_STATUS_ERROR)
3803 xml_failure(g_parser);
3804 if (XML_GetBuffer(g_parser, INT_MAX) != NULL)
3805 fail("INT_MAX buffer not failed");
3806
3807 /* Now try extending it a more reasonable but still too large
3808 * amount. The allocator in XML_GetBuffer() doubles the buffer
3809 * size until it exceeds the requested amount or INT_MAX. If it
3810 * exceeds INT_MAX, it rejects the request, so we want a request
3811 * between INT_MAX and INT_MAX/2. A gap of 1K seems comfortable,
3812 * with an extra byte just to ensure that the request is off any
3813 * boundary. The request will be inflated internally by
3814 * XML_CONTEXT_BYTES (if defined), so we subtract that from our
3815 * request.
3816 */
3817 if (get_feature(XML_FEATURE_CONTEXT_BYTES, &context_bytes) != XML_STATUS_OK)
3818 context_bytes = 0;
3819 if (XML_GetBuffer(g_parser, INT_MAX - (context_bytes + 1025)) != NULL)
3820 fail("INT_MAX- buffer not failed");
3821
3822 /* Now try extending it a carefully crafted amount */
3823 if (XML_GetBuffer(g_parser, 1000) == NULL)
3824 fail("1000 buffer failed");
3825 }
3826 END_TEST
3827
3828 /* Test more corners of the XML_GetBuffer interface */
START_TEST(test_get_buffer_2)3829 START_TEST(test_get_buffer_2) {
3830 const char *text = get_buffer_test_text;
3831 void *buffer;
3832
3833 /* Now get a decent buffer */
3834 buffer = XML_GetBuffer(g_parser, 1536);
3835 if (buffer == NULL)
3836 fail("1.5K buffer failed");
3837 assert(buffer != NULL);
3838 memcpy(buffer, text, strlen(text));
3839 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE)
3840 == XML_STATUS_ERROR)
3841 xml_failure(g_parser);
3842
3843 /* Extend it, to catch a different code path */
3844 if (XML_GetBuffer(g_parser, 1024) == NULL)
3845 fail("1024 buffer failed");
3846 }
3847 END_TEST
3848
3849 /* Test position information macros */
START_TEST(test_byte_info_at_end)3850 START_TEST(test_byte_info_at_end) {
3851 const char *text = "<doc></doc>";
3852
3853 if (XML_GetCurrentByteIndex(g_parser) != -1
3854 || XML_GetCurrentByteCount(g_parser) != 0)
3855 fail("Byte index/count incorrect at start of parse");
3856 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3857 == XML_STATUS_ERROR)
3858 xml_failure(g_parser);
3859 /* At end, the count will be zero and the index the end of string */
3860 if (XML_GetCurrentByteCount(g_parser) != 0)
3861 fail("Terminal byte count incorrect");
3862 if (XML_GetCurrentByteIndex(g_parser) != (XML_Index)strlen(text))
3863 fail("Terminal byte index incorrect");
3864 }
3865 END_TEST
3866
3867 /* Test position information from errors */
3868 #define PRE_ERROR_STR "<doc></"
3869 #define POST_ERROR_STR "wombat></doc>"
START_TEST(test_byte_info_at_error)3870 START_TEST(test_byte_info_at_error) {
3871 const char *text = PRE_ERROR_STR POST_ERROR_STR;
3872
3873 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3874 == XML_STATUS_OK)
3875 fail("Syntax error not faulted");
3876 if (XML_GetCurrentByteCount(g_parser) != 0)
3877 fail("Error byte count incorrect");
3878 if (XML_GetCurrentByteIndex(g_parser) != strlen(PRE_ERROR_STR))
3879 fail("Error byte index incorrect");
3880 }
3881 END_TEST
3882 #undef PRE_ERROR_STR
3883 #undef POST_ERROR_STR
3884
3885 /* Test position information in handler */
3886 typedef struct ByteTestData {
3887 int start_element_len;
3888 int cdata_len;
3889 int total_string_len;
3890 } ByteTestData;
3891
3892 static void
byte_character_handler(void * userData,const XML_Char * s,int len)3893 byte_character_handler(void *userData, const XML_Char *s, int len) {
3894 #ifdef XML_CONTEXT_BYTES
3895 int offset, size;
3896 const char *buffer;
3897 ByteTestData *data = (ByteTestData *)userData;
3898
3899 UNUSED_P(s);
3900 buffer = XML_GetInputContext(g_parser, &offset, &size);
3901 if (buffer == NULL)
3902 fail("Failed to get context buffer");
3903 if (offset != data->start_element_len)
3904 fail("Context offset in unexpected position");
3905 if (len != data->cdata_len)
3906 fail("CDATA length reported incorrectly");
3907 if (size != data->total_string_len)
3908 fail("Context size is not full buffer");
3909 if (XML_GetCurrentByteIndex(g_parser) != offset)
3910 fail("Character byte index incorrect");
3911 if (XML_GetCurrentByteCount(g_parser) != len)
3912 fail("Character byte count incorrect");
3913 #else
3914 UNUSED_P(s);
3915 UNUSED_P(userData);
3916 UNUSED_P(len);
3917 #endif
3918 }
3919
3920 #define START_ELEMENT "<e>"
3921 #define CDATA_TEXT "Hello"
3922 #define END_ELEMENT "</e>"
START_TEST(test_byte_info_at_cdata)3923 START_TEST(test_byte_info_at_cdata) {
3924 const char *text = START_ELEMENT CDATA_TEXT END_ELEMENT;
3925 int offset, size;
3926 ByteTestData data;
3927
3928 /* Check initial context is empty */
3929 if (XML_GetInputContext(g_parser, &offset, &size) != NULL)
3930 fail("Unexpected context at start of parse");
3931
3932 data.start_element_len = (int)strlen(START_ELEMENT);
3933 data.cdata_len = (int)strlen(CDATA_TEXT);
3934 data.total_string_len = (int)strlen(text);
3935 XML_SetCharacterDataHandler(g_parser, byte_character_handler);
3936 XML_SetUserData(g_parser, &data);
3937 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_OK)
3938 xml_failure(g_parser);
3939 }
3940 END_TEST
3941 #undef START_ELEMENT
3942 #undef CDATA_TEXT
3943 #undef END_ELEMENT
3944
3945 /* Test predefined entities are correctly recognised */
START_TEST(test_predefined_entities)3946 START_TEST(test_predefined_entities) {
3947 const char *text = "<doc><>&"'</doc>";
3948 const XML_Char *expected = XCS("<doc><>&"'</doc>");
3949 const XML_Char *result = XCS("<>&\"'");
3950 CharData storage;
3951
3952 XML_SetDefaultHandler(g_parser, accumulate_characters);
3953 /* run_character_check uses XML_SetCharacterDataHandler(), which
3954 * unfortunately heads off a code path that we need to exercise.
3955 */
3956 CharData_Init(&storage);
3957 XML_SetUserData(g_parser, &storage);
3958 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3959 == XML_STATUS_ERROR)
3960 xml_failure(g_parser);
3961 /* The default handler doesn't translate the entities */
3962 CharData_CheckXMLChars(&storage, expected);
3963
3964 /* Now try again and check the translation */
3965 XML_ParserReset(g_parser, NULL);
3966 run_character_check(text, result);
3967 }
3968 END_TEST
3969
3970 /* Regression test that an invalid tag in an external parameter
3971 * reference in an external DTD is correctly faulted.
3972 *
3973 * Only a few specific tags are legal in DTDs ignoring comments and
3974 * processing instructions, all of which begin with an exclamation
3975 * mark. "<el/>" is not one of them, so the parser should raise an
3976 * error on encountering it.
3977 */
3978 static int XMLCALL
external_entity_param(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)3979 external_entity_param(XML_Parser parser, const XML_Char *context,
3980 const XML_Char *base, const XML_Char *systemId,
3981 const XML_Char *publicId) {
3982 const char *text1 = "<!ELEMENT doc EMPTY>\n"
3983 "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
3984 "<!ENTITY % e2 '%e1;'>\n"
3985 "%e1;\n";
3986 const char *text2 = "<!ELEMENT el EMPTY>\n"
3987 "<el/>\n";
3988 XML_Parser ext_parser;
3989
3990 UNUSED_P(base);
3991 UNUSED_P(publicId);
3992 if (systemId == NULL)
3993 return XML_STATUS_OK;
3994
3995 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3996 if (ext_parser == NULL)
3997 fail("Could not create external entity parser");
3998
3999 if (! xcstrcmp(systemId, XCS("004-1.ent"))) {
4000 if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
4001 != XML_STATUS_ERROR)
4002 fail("Inner DTD with invalid tag not rejected");
4003 if (XML_GetErrorCode(ext_parser) != XML_ERROR_EXTERNAL_ENTITY_HANDLING)
4004 xml_failure(ext_parser);
4005 } else if (! xcstrcmp(systemId, XCS("004-2.ent"))) {
4006 if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE)
4007 != XML_STATUS_ERROR)
4008 fail("Invalid tag in external param not rejected");
4009 if (XML_GetErrorCode(ext_parser) != XML_ERROR_SYNTAX)
4010 xml_failure(ext_parser);
4011 } else {
4012 fail("Unknown system ID");
4013 }
4014
4015 XML_ParserFree(ext_parser);
4016 return XML_STATUS_ERROR;
4017 }
4018
START_TEST(test_invalid_tag_in_dtd)4019 START_TEST(test_invalid_tag_in_dtd) {
4020 const char *text = "<!DOCTYPE doc SYSTEM '004-1.ent'>\n"
4021 "<doc></doc>\n";
4022
4023 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4024 XML_SetExternalEntityRefHandler(g_parser, external_entity_param);
4025 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
4026 "Invalid tag IN DTD external param not rejected");
4027 }
4028 END_TEST
4029
4030 /* Test entities not quite the predefined ones are not mis-recognised */
START_TEST(test_not_predefined_entities)4031 START_TEST(test_not_predefined_entities) {
4032 const char *text[] = {"<doc>&pt;</doc>", "<doc>&amo;</doc>",
4033 "<doc>&quid;</doc>", "<doc>&apod;</doc>", NULL};
4034 int i = 0;
4035
4036 while (text[i] != NULL) {
4037 expect_failure(text[i], XML_ERROR_UNDEFINED_ENTITY,
4038 "Undefined entity not rejected");
4039 XML_ParserReset(g_parser, NULL);
4040 i++;
4041 }
4042 }
4043 END_TEST
4044
4045 /* Test conditional inclusion (IGNORE) */
4046 static int XMLCALL
external_entity_load_ignore(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)4047 external_entity_load_ignore(XML_Parser parser, const XML_Char *context,
4048 const XML_Char *base, const XML_Char *systemId,
4049 const XML_Char *publicId) {
4050 const char *text = "<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>";
4051 XML_Parser ext_parser;
4052
4053 UNUSED_P(base);
4054 UNUSED_P(systemId);
4055 UNUSED_P(publicId);
4056 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4057 if (ext_parser == NULL)
4058 fail("Could not create external entity parser");
4059 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
4060 == XML_STATUS_ERROR)
4061 xml_failure(parser);
4062
4063 XML_ParserFree(ext_parser);
4064 return XML_STATUS_OK;
4065 }
4066
START_TEST(test_ignore_section)4067 START_TEST(test_ignore_section) {
4068 const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
4069 "<doc><e>&entity;</e></doc>";
4070 const XML_Char *expected
4071 = XCS("<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>\n&entity;");
4072 CharData storage;
4073
4074 CharData_Init(&storage);
4075 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4076 XML_SetUserData(g_parser, &storage);
4077 XML_SetExternalEntityRefHandler(g_parser, external_entity_load_ignore);
4078 XML_SetDefaultHandler(g_parser, accumulate_characters);
4079 XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler);
4080 XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler);
4081 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4082 XML_SetStartElementHandler(g_parser, dummy_start_element);
4083 XML_SetEndElementHandler(g_parser, dummy_end_element);
4084 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4085 == XML_STATUS_ERROR)
4086 xml_failure(g_parser);
4087 CharData_CheckXMLChars(&storage, expected);
4088 }
4089 END_TEST
4090
4091 static int XMLCALL
external_entity_load_ignore_utf16(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)4092 external_entity_load_ignore_utf16(XML_Parser parser, const XML_Char *context,
4093 const XML_Char *base,
4094 const XML_Char *systemId,
4095 const XML_Char *publicId) {
4096 const char text[] =
4097 /* <![IGNORE[<!ELEMENT e (#PCDATA)*>]]> */
4098 "<\0!\0[\0I\0G\0N\0O\0R\0E\0[\0"
4099 "<\0!\0E\0L\0E\0M\0E\0N\0T\0 \0e\0 \0"
4100 "(\0#\0P\0C\0D\0A\0T\0A\0)\0*\0>\0]\0]\0>\0";
4101 XML_Parser ext_parser;
4102
4103 UNUSED_P(base);
4104 UNUSED_P(systemId);
4105 UNUSED_P(publicId);
4106 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4107 if (ext_parser == NULL)
4108 fail("Could not create external entity parser");
4109 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)sizeof(text) - 1, XML_TRUE)
4110 == XML_STATUS_ERROR)
4111 xml_failure(parser);
4112
4113 XML_ParserFree(ext_parser);
4114 return XML_STATUS_OK;
4115 }
4116
START_TEST(test_ignore_section_utf16)4117 START_TEST(test_ignore_section_utf16) {
4118 const char text[] =
4119 /* <!DOCTYPE d SYSTEM 's'> */
4120 "<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 "
4121 "\0S\0Y\0S\0T\0E\0M\0 \0'\0s\0'\0>\0\n\0"
4122 /* <d><e>&en;</e></d> */
4123 "<\0d\0>\0<\0e\0>\0&\0e\0n\0;\0<\0/\0e\0>\0<\0/\0d\0>\0";
4124 const XML_Char *expected = XCS("<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>\n&en;");
4125 CharData storage;
4126
4127 CharData_Init(&storage);
4128 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4129 XML_SetUserData(g_parser, &storage);
4130 XML_SetExternalEntityRefHandler(g_parser, external_entity_load_ignore_utf16);
4131 XML_SetDefaultHandler(g_parser, accumulate_characters);
4132 XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler);
4133 XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler);
4134 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4135 XML_SetStartElementHandler(g_parser, dummy_start_element);
4136 XML_SetEndElementHandler(g_parser, dummy_end_element);
4137 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
4138 == XML_STATUS_ERROR)
4139 xml_failure(g_parser);
4140 CharData_CheckXMLChars(&storage, expected);
4141 }
4142 END_TEST
4143
4144 static int XMLCALL
external_entity_load_ignore_utf16_be(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)4145 external_entity_load_ignore_utf16_be(XML_Parser parser, const XML_Char *context,
4146 const XML_Char *base,
4147 const XML_Char *systemId,
4148 const XML_Char *publicId) {
4149 const char text[] =
4150 /* <![IGNORE[<!ELEMENT e (#PCDATA)*>]]> */
4151 "\0<\0!\0[\0I\0G\0N\0O\0R\0E\0["
4152 "\0<\0!\0E\0L\0E\0M\0E\0N\0T\0 \0e\0 "
4153 "\0(\0#\0P\0C\0D\0A\0T\0A\0)\0*\0>\0]\0]\0>";
4154 XML_Parser ext_parser;
4155
4156 UNUSED_P(base);
4157 UNUSED_P(systemId);
4158 UNUSED_P(publicId);
4159 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4160 if (ext_parser == NULL)
4161 fail("Could not create external entity parser");
4162 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)sizeof(text) - 1, XML_TRUE)
4163 == XML_STATUS_ERROR)
4164 xml_failure(parser);
4165
4166 XML_ParserFree(ext_parser);
4167 return XML_STATUS_OK;
4168 }
4169
START_TEST(test_ignore_section_utf16_be)4170 START_TEST(test_ignore_section_utf16_be) {
4171 const char text[] =
4172 /* <!DOCTYPE d SYSTEM 's'> */
4173 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 "
4174 "\0S\0Y\0S\0T\0E\0M\0 \0'\0s\0'\0>\0\n"
4175 /* <d><e>&en;</e></d> */
4176 "\0<\0d\0>\0<\0e\0>\0&\0e\0n\0;\0<\0/\0e\0>\0<\0/\0d\0>";
4177 const XML_Char *expected = XCS("<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>\n&en;");
4178 CharData storage;
4179
4180 CharData_Init(&storage);
4181 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4182 XML_SetUserData(g_parser, &storage);
4183 XML_SetExternalEntityRefHandler(g_parser,
4184 external_entity_load_ignore_utf16_be);
4185 XML_SetDefaultHandler(g_parser, accumulate_characters);
4186 XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler);
4187 XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler);
4188 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4189 XML_SetStartElementHandler(g_parser, dummy_start_element);
4190 XML_SetEndElementHandler(g_parser, dummy_end_element);
4191 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
4192 == XML_STATUS_ERROR)
4193 xml_failure(g_parser);
4194 CharData_CheckXMLChars(&storage, expected);
4195 }
4196 END_TEST
4197
4198 /* Test mis-formatted conditional exclusion */
START_TEST(test_bad_ignore_section)4199 START_TEST(test_bad_ignore_section) {
4200 const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
4201 "<doc><e>&entity;</e></doc>";
4202 ExtFaults faults[]
4203 = {{"<![IGNORE[<!ELEM", "Broken-off declaration not faulted", NULL,
4204 XML_ERROR_SYNTAX},
4205 {"<![IGNORE[\x01]]>", "Invalid XML character not faulted", NULL,
4206 XML_ERROR_INVALID_TOKEN},
4207 {/* FIrst two bytes of a three-byte char */
4208 "<![IGNORE[\xe2\x82", "Partial XML character not faulted", NULL,
4209 XML_ERROR_PARTIAL_CHAR},
4210 {NULL, NULL, NULL, XML_ERROR_NONE}};
4211 ExtFaults *fault;
4212
4213 for (fault = &faults[0]; fault->parse_text != NULL; fault++) {
4214 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4215 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
4216 XML_SetUserData(g_parser, fault);
4217 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
4218 "Incomplete IGNORE section not failed");
4219 XML_ParserReset(g_parser, NULL);
4220 }
4221 }
4222 END_TEST
4223
4224 /* Test recursive parsing */
4225 static int XMLCALL
external_entity_valuer(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)4226 external_entity_valuer(XML_Parser parser, const XML_Char *context,
4227 const XML_Char *base, const XML_Char *systemId,
4228 const XML_Char *publicId) {
4229 const char *text1 = "<!ELEMENT doc EMPTY>\n"
4230 "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
4231 "<!ENTITY % e2 '%e1;'>\n"
4232 "%e1;\n";
4233 XML_Parser ext_parser;
4234
4235 UNUSED_P(base);
4236 UNUSED_P(publicId);
4237 if (systemId == NULL)
4238 return XML_STATUS_OK;
4239 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4240 if (ext_parser == NULL)
4241 fail("Could not create external entity parser");
4242 if (! xcstrcmp(systemId, XCS("004-1.ent"))) {
4243 if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
4244 == XML_STATUS_ERROR)
4245 xml_failure(ext_parser);
4246 } else if (! xcstrcmp(systemId, XCS("004-2.ent"))) {
4247 ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser);
4248 enum XML_Status status;
4249 enum XML_Error error;
4250
4251 status = _XML_Parse_SINGLE_BYTES(ext_parser, fault->parse_text,
4252 (int)strlen(fault->parse_text), XML_TRUE);
4253 if (fault->error == XML_ERROR_NONE) {
4254 if (status == XML_STATUS_ERROR)
4255 xml_failure(ext_parser);
4256 } else {
4257 if (status != XML_STATUS_ERROR)
4258 fail(fault->fail_text);
4259 error = XML_GetErrorCode(ext_parser);
4260 if (error != fault->error
4261 && (fault->error != XML_ERROR_XML_DECL
4262 || error != XML_ERROR_TEXT_DECL))
4263 xml_failure(ext_parser);
4264 }
4265 }
4266
4267 XML_ParserFree(ext_parser);
4268 return XML_STATUS_OK;
4269 }
4270
START_TEST(test_external_entity_values)4271 START_TEST(test_external_entity_values) {
4272 const char *text = "<!DOCTYPE doc SYSTEM '004-1.ent'>\n"
4273 "<doc></doc>\n";
4274 ExtFaults data_004_2[] = {
4275 {"<!ATTLIST doc a1 CDATA 'value'>", NULL, NULL, XML_ERROR_NONE},
4276 {"<!ATTLIST $doc a1 CDATA 'value'>", "Invalid token not faulted", NULL,
4277 XML_ERROR_INVALID_TOKEN},
4278 {"'wombat", "Unterminated string not faulted", NULL,
4279 XML_ERROR_UNCLOSED_TOKEN},
4280 {"\xe2\x82", "Partial UTF-8 character not faulted", NULL,
4281 XML_ERROR_PARTIAL_CHAR},
4282 {"<?xml version='1.0' encoding='utf-8'?>\n", NULL, NULL, XML_ERROR_NONE},
4283 {"<?xml?>", "Malformed XML declaration not faulted", NULL,
4284 XML_ERROR_XML_DECL},
4285 {/* UTF-8 BOM */
4286 "\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>", NULL, NULL,
4287 XML_ERROR_NONE},
4288 {"<?xml version='1.0' encoding='utf-8'?>\n$",
4289 "Invalid token after text declaration not faulted", NULL,
4290 XML_ERROR_INVALID_TOKEN},
4291 {"<?xml version='1.0' encoding='utf-8'?>\n'wombat",
4292 "Unterminated string after text decl not faulted", NULL,
4293 XML_ERROR_UNCLOSED_TOKEN},
4294 {"<?xml version='1.0' encoding='utf-8'?>\n\xe2\x82",
4295 "Partial UTF-8 character after text decl not faulted", NULL,
4296 XML_ERROR_PARTIAL_CHAR},
4297 {"%e1;", "Recursive parameter entity not faulted", NULL,
4298 XML_ERROR_RECURSIVE_ENTITY_REF},
4299 {NULL, NULL, NULL, XML_ERROR_NONE}};
4300 int i;
4301
4302 for (i = 0; data_004_2[i].parse_text != NULL; i++) {
4303 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4304 XML_SetExternalEntityRefHandler(g_parser, external_entity_valuer);
4305 XML_SetUserData(g_parser, &data_004_2[i]);
4306 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4307 == XML_STATUS_ERROR)
4308 xml_failure(g_parser);
4309 XML_ParserReset(g_parser, NULL);
4310 }
4311 }
4312 END_TEST
4313
4314 /* Test the recursive parse interacts with a not standalone handler */
4315 static int XMLCALL
external_entity_not_standalone(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)4316 external_entity_not_standalone(XML_Parser parser, const XML_Char *context,
4317 const XML_Char *base, const XML_Char *systemId,
4318 const XML_Char *publicId) {
4319 const char *text1 = "<!ELEMENT doc EMPTY>\n"
4320 "<!ENTITY % e1 SYSTEM 'bar'>\n"
4321 "%e1;\n";
4322 const char *text2 = "<!ATTLIST doc a1 CDATA 'value'>";
4323 XML_Parser ext_parser;
4324
4325 UNUSED_P(base);
4326 UNUSED_P(publicId);
4327 if (systemId == NULL)
4328 return XML_STATUS_OK;
4329 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4330 if (ext_parser == NULL)
4331 fail("Could not create external entity parser");
4332 if (! xcstrcmp(systemId, XCS("foo"))) {
4333 XML_SetNotStandaloneHandler(ext_parser, reject_not_standalone_handler);
4334 if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
4335 != XML_STATUS_ERROR)
4336 fail("Expected not standalone rejection");
4337 if (XML_GetErrorCode(ext_parser) != XML_ERROR_NOT_STANDALONE)
4338 xml_failure(ext_parser);
4339 XML_SetNotStandaloneHandler(ext_parser, NULL);
4340 XML_ParserFree(ext_parser);
4341 return XML_STATUS_ERROR;
4342 } else if (! xcstrcmp(systemId, XCS("bar"))) {
4343 if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE)
4344 == XML_STATUS_ERROR)
4345 xml_failure(ext_parser);
4346 }
4347
4348 XML_ParserFree(ext_parser);
4349 return XML_STATUS_OK;
4350 }
4351
START_TEST(test_ext_entity_not_standalone)4352 START_TEST(test_ext_entity_not_standalone) {
4353 const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
4354 "<doc></doc>";
4355
4356 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4357 XML_SetExternalEntityRefHandler(g_parser, external_entity_not_standalone);
4358 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
4359 "Standalone rejection not caught");
4360 }
4361 END_TEST
4362
4363 static int XMLCALL
external_entity_value_aborter(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)4364 external_entity_value_aborter(XML_Parser parser, const XML_Char *context,
4365 const XML_Char *base, const XML_Char *systemId,
4366 const XML_Char *publicId) {
4367 const char *text1 = "<!ELEMENT doc EMPTY>\n"
4368 "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
4369 "<!ENTITY % e2 '%e1;'>\n"
4370 "%e1;\n";
4371 const char *text2 = "<?xml version='1.0' encoding='utf-8'?>";
4372 XML_Parser ext_parser;
4373
4374 UNUSED_P(base);
4375 UNUSED_P(publicId);
4376 if (systemId == NULL)
4377 return XML_STATUS_OK;
4378 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4379 if (ext_parser == NULL)
4380 fail("Could not create external entity parser");
4381 if (! xcstrcmp(systemId, XCS("004-1.ent"))) {
4382 if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
4383 == XML_STATUS_ERROR)
4384 xml_failure(ext_parser);
4385 }
4386 if (! xcstrcmp(systemId, XCS("004-2.ent"))) {
4387 XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
4388 XML_SetUserData(ext_parser, ext_parser);
4389 if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE)
4390 != XML_STATUS_ERROR)
4391 fail("Aborted parse not faulted");
4392 if (XML_GetErrorCode(ext_parser) != XML_ERROR_ABORTED)
4393 xml_failure(ext_parser);
4394 }
4395
4396 XML_ParserFree(ext_parser);
4397 return XML_STATUS_OK;
4398 }
4399
START_TEST(test_ext_entity_value_abort)4400 START_TEST(test_ext_entity_value_abort) {
4401 const char *text = "<!DOCTYPE doc SYSTEM '004-1.ent'>\n"
4402 "<doc></doc>\n";
4403
4404 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4405 XML_SetExternalEntityRefHandler(g_parser, external_entity_value_aborter);
4406 resumable = XML_FALSE;
4407 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4408 == XML_STATUS_ERROR)
4409 xml_failure(g_parser);
4410 }
4411 END_TEST
4412
START_TEST(test_bad_public_doctype)4413 START_TEST(test_bad_public_doctype) {
4414 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
4415 "<!DOCTYPE doc PUBLIC '{BadName}' 'test'>\n"
4416 "<doc></doc>";
4417
4418 /* Setting a handler provokes a particular code path */
4419 XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_handler,
4420 dummy_end_doctype_handler);
4421 expect_failure(text, XML_ERROR_PUBLICID, "Bad Public ID not failed");
4422 }
4423 END_TEST
4424
4425 /* Test based on ibm/valid/P32/ibm32v04.xml */
START_TEST(test_attribute_enum_value)4426 START_TEST(test_attribute_enum_value) {
4427 const char *text = "<?xml version='1.0' standalone='no'?>\n"
4428 "<!DOCTYPE animal SYSTEM 'test.dtd'>\n"
4429 "<animal>This is a \n <a/> \n\nyellow tiger</animal>";
4430 ExtTest dtd_data
4431 = {"<!ELEMENT animal (#PCDATA|a)*>\n"
4432 "<!ELEMENT a EMPTY>\n"
4433 "<!ATTLIST animal xml:space (default|preserve) 'preserve'>",
4434 NULL, NULL};
4435 const XML_Char *expected = XCS("This is a \n \n\nyellow tiger");
4436
4437 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
4438 XML_SetUserData(g_parser, &dtd_data);
4439 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4440 /* An attribute list handler provokes a different code path */
4441 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
4442 run_ext_character_check(text, &dtd_data, expected);
4443 }
4444 END_TEST
4445
4446 /* Slightly bizarrely, the library seems to silently ignore entity
4447 * definitions for predefined entities, even when they are wrong. The
4448 * language of the XML 1.0 spec is somewhat unhelpful as to what ought
4449 * to happen, so this is currently treated as acceptable.
4450 */
START_TEST(test_predefined_entity_redefinition)4451 START_TEST(test_predefined_entity_redefinition) {
4452 const char *text = "<!DOCTYPE doc [\n"
4453 "<!ENTITY apos 'foo'>\n"
4454 "]>\n"
4455 "<doc>'</doc>";
4456 run_character_check(text, XCS("'"));
4457 }
4458 END_TEST
4459
4460 /* Test that the parser stops processing the DTD after an unresolved
4461 * parameter entity is encountered.
4462 */
START_TEST(test_dtd_stop_processing)4463 START_TEST(test_dtd_stop_processing) {
4464 const char *text = "<!DOCTYPE doc [\n"
4465 "%foo;\n"
4466 "<!ENTITY bar 'bas'>\n"
4467 "]><doc/>";
4468
4469 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
4470 dummy_handler_flags = 0;
4471 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4472 == XML_STATUS_ERROR)
4473 xml_failure(g_parser);
4474 if (dummy_handler_flags != 0)
4475 fail("DTD processing still going after undefined PE");
4476 }
4477 END_TEST
4478
4479 /* Test public notations with no system ID */
START_TEST(test_public_notation_no_sysid)4480 START_TEST(test_public_notation_no_sysid) {
4481 const char *text = "<!DOCTYPE doc [\n"
4482 "<!NOTATION note PUBLIC 'foo'>\n"
4483 "<!ELEMENT doc EMPTY>\n"
4484 "]>\n<doc/>";
4485
4486 dummy_handler_flags = 0;
4487 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
4488 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4489 == XML_STATUS_ERROR)
4490 xml_failure(g_parser);
4491 if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG)
4492 fail("Notation declaration handler not called");
4493 }
4494 END_TEST
4495
4496 static void XMLCALL
record_element_start_handler(void * userData,const XML_Char * name,const XML_Char ** atts)4497 record_element_start_handler(void *userData, const XML_Char *name,
4498 const XML_Char **atts) {
4499 UNUSED_P(atts);
4500 CharData_AppendXMLChars((CharData *)userData, name, (int)xcstrlen(name));
4501 }
4502
START_TEST(test_nested_groups)4503 START_TEST(test_nested_groups) {
4504 const char *text
4505 = "<!DOCTYPE doc [\n"
4506 "<!ELEMENT doc "
4507 /* Sixteen elements per line */
4508 "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,"
4509 "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?"
4510 "))))))))))))))))))))))))))))))))>\n"
4511 "<!ELEMENT e EMPTY>"
4512 "]>\n"
4513 "<doc><e/></doc>";
4514 CharData storage;
4515
4516 CharData_Init(&storage);
4517 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4518 XML_SetStartElementHandler(g_parser, record_element_start_handler);
4519 XML_SetUserData(g_parser, &storage);
4520 dummy_handler_flags = 0;
4521 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4522 == XML_STATUS_ERROR)
4523 xml_failure(g_parser);
4524 CharData_CheckXMLChars(&storage, XCS("doce"));
4525 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
4526 fail("Element handler not fired");
4527 }
4528 END_TEST
4529
START_TEST(test_group_choice)4530 START_TEST(test_group_choice) {
4531 const char *text = "<!DOCTYPE doc [\n"
4532 "<!ELEMENT doc (a|b|c)+>\n"
4533 "<!ELEMENT a EMPTY>\n"
4534 "<!ELEMENT b (#PCDATA)>\n"
4535 "<!ELEMENT c ANY>\n"
4536 "]>\n"
4537 "<doc>\n"
4538 "<a/>\n"
4539 "<b attr='foo'>This is a foo</b>\n"
4540 "<c></c>\n"
4541 "</doc>\n";
4542
4543 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4544 dummy_handler_flags = 0;
4545 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4546 == XML_STATUS_ERROR)
4547 xml_failure(g_parser);
4548 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
4549 fail("Element handler flag not raised");
4550 }
4551 END_TEST
4552
4553 static int XMLCALL
external_entity_public(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)4554 external_entity_public(XML_Parser parser, const XML_Char *context,
4555 const XML_Char *base, const XML_Char *systemId,
4556 const XML_Char *publicId) {
4557 const char *text1 = (const char *)XML_GetUserData(parser);
4558 const char *text2 = "<!ATTLIST doc a CDATA 'value'>";
4559 const char *text = NULL;
4560 XML_Parser ext_parser;
4561 int parse_res;
4562
4563 UNUSED_P(base);
4564 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4565 if (ext_parser == NULL)
4566 return XML_STATUS_ERROR;
4567 if (systemId != NULL && ! xcstrcmp(systemId, XCS("http://example.org/"))) {
4568 text = text1;
4569 } else if (publicId != NULL && ! xcstrcmp(publicId, XCS("foo"))) {
4570 text = text2;
4571 } else
4572 fail("Unexpected parameters to external entity parser");
4573 assert(text != NULL);
4574 parse_res
4575 = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
4576 XML_ParserFree(ext_parser);
4577 return parse_res;
4578 }
4579
START_TEST(test_standalone_parameter_entity)4580 START_TEST(test_standalone_parameter_entity) {
4581 const char *text = "<?xml version='1.0' standalone='yes'?>\n"
4582 "<!DOCTYPE doc SYSTEM 'http://example.org/' [\n"
4583 "<!ENTITY % entity '<!ELEMENT doc (#PCDATA)>'>\n"
4584 "%entity;\n"
4585 "]>\n"
4586 "<doc></doc>";
4587 char dtd_data[] = "<!ENTITY % e1 'foo'>\n";
4588
4589 XML_SetUserData(g_parser, dtd_data);
4590 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4591 XML_SetExternalEntityRefHandler(g_parser, external_entity_public);
4592 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4593 == XML_STATUS_ERROR)
4594 xml_failure(g_parser);
4595 }
4596 END_TEST
4597
4598 /* Test skipping of parameter entity in an external DTD */
4599 /* Derived from ibm/invalid/P69/ibm69i01.xml */
START_TEST(test_skipped_parameter_entity)4600 START_TEST(test_skipped_parameter_entity) {
4601 const char *text = "<?xml version='1.0'?>\n"
4602 "<!DOCTYPE root SYSTEM 'http://example.org/dtd.ent' [\n"
4603 "<!ELEMENT root (#PCDATA|a)* >\n"
4604 "]>\n"
4605 "<root></root>";
4606 ExtTest dtd_data = {"%pe2;", NULL, NULL};
4607
4608 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
4609 XML_SetUserData(g_parser, &dtd_data);
4610 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4611 XML_SetSkippedEntityHandler(g_parser, dummy_skip_handler);
4612 dummy_handler_flags = 0;
4613 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4614 == XML_STATUS_ERROR)
4615 xml_failure(g_parser);
4616 if (dummy_handler_flags != DUMMY_SKIP_HANDLER_FLAG)
4617 fail("Skip handler not executed");
4618 }
4619 END_TEST
4620
4621 /* Test recursive parameter entity definition rejected in external DTD */
START_TEST(test_recursive_external_parameter_entity)4622 START_TEST(test_recursive_external_parameter_entity) {
4623 const char *text = "<?xml version='1.0'?>\n"
4624 "<!DOCTYPE root SYSTEM 'http://example.org/dtd.ent' [\n"
4625 "<!ELEMENT root (#PCDATA|a)* >\n"
4626 "]>\n"
4627 "<root></root>";
4628 ExtFaults dtd_data = {"<!ENTITY % pe2 '%pe2;'>\n%pe2;",
4629 "Recursive external parameter entity not faulted", NULL,
4630 XML_ERROR_RECURSIVE_ENTITY_REF};
4631
4632 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
4633 XML_SetUserData(g_parser, &dtd_data);
4634 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4635 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
4636 "Recursive external parameter not spotted");
4637 }
4638 END_TEST
4639
4640 /* Test undefined parameter entity in external entity handler */
4641 static int XMLCALL
external_entity_devaluer(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)4642 external_entity_devaluer(XML_Parser parser, const XML_Char *context,
4643 const XML_Char *base, const XML_Char *systemId,
4644 const XML_Char *publicId) {
4645 const char *text = "<!ELEMENT doc EMPTY>\n"
4646 "<!ENTITY % e1 SYSTEM 'bar'>\n"
4647 "%e1;\n";
4648 XML_Parser ext_parser;
4649 intptr_t clear_handler = (intptr_t)XML_GetUserData(parser);
4650
4651 UNUSED_P(base);
4652 UNUSED_P(publicId);
4653 if (systemId == NULL || ! xcstrcmp(systemId, XCS("bar")))
4654 return XML_STATUS_OK;
4655 if (xcstrcmp(systemId, XCS("foo")))
4656 fail("Unexpected system ID");
4657 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4658 if (ext_parser == NULL)
4659 fail("Could note create external entity parser");
4660 if (clear_handler)
4661 XML_SetExternalEntityRefHandler(ext_parser, NULL);
4662 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
4663 == XML_STATUS_ERROR)
4664 xml_failure(ext_parser);
4665
4666 XML_ParserFree(ext_parser);
4667 return XML_STATUS_OK;
4668 }
4669
START_TEST(test_undefined_ext_entity_in_external_dtd)4670 START_TEST(test_undefined_ext_entity_in_external_dtd) {
4671 const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
4672 "<doc></doc>\n";
4673
4674 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4675 XML_SetExternalEntityRefHandler(g_parser, external_entity_devaluer);
4676 XML_SetUserData(g_parser, (void *)(intptr_t)XML_FALSE);
4677 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4678 == XML_STATUS_ERROR)
4679 xml_failure(g_parser);
4680
4681 /* Now repeat without the external entity ref handler invoking
4682 * another copy of itself.
4683 */
4684 XML_ParserReset(g_parser, NULL);
4685 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4686 XML_SetExternalEntityRefHandler(g_parser, external_entity_devaluer);
4687 XML_SetUserData(g_parser, (void *)(intptr_t)XML_TRUE);
4688 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4689 == XML_STATUS_ERROR)
4690 xml_failure(g_parser);
4691 }
4692 END_TEST
4693
4694 static void XMLCALL
aborting_xdecl_handler(void * userData,const XML_Char * version,const XML_Char * encoding,int standalone)4695 aborting_xdecl_handler(void *userData, const XML_Char *version,
4696 const XML_Char *encoding, int standalone) {
4697 UNUSED_P(userData);
4698 UNUSED_P(version);
4699 UNUSED_P(encoding);
4700 UNUSED_P(standalone);
4701 XML_StopParser(g_parser, resumable);
4702 XML_SetXmlDeclHandler(g_parser, NULL);
4703 }
4704
4705 /* Test suspending the parse on receiving an XML declaration works */
START_TEST(test_suspend_xdecl)4706 START_TEST(test_suspend_xdecl) {
4707 const char *text = long_character_data_text;
4708
4709 XML_SetXmlDeclHandler(g_parser, aborting_xdecl_handler);
4710 resumable = XML_TRUE;
4711 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4712 != XML_STATUS_SUSPENDED)
4713 xml_failure(g_parser);
4714 if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE)
4715 xml_failure(g_parser);
4716 /* Attempt to start a new parse while suspended */
4717 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
4718 != XML_STATUS_ERROR)
4719 fail("Attempt to parse while suspended not faulted");
4720 if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED)
4721 fail("Suspended parse not faulted with correct error");
4722 }
4723 END_TEST
4724
4725 /* Test aborting the parse in an epilog works */
4726 static void XMLCALL
selective_aborting_default_handler(void * userData,const XML_Char * s,int len)4727 selective_aborting_default_handler(void *userData, const XML_Char *s, int len) {
4728 const XML_Char *match = (const XML_Char *)userData;
4729
4730 if (match == NULL
4731 || (xcstrlen(match) == (unsigned)len && ! xcstrncmp(match, s, len))) {
4732 XML_StopParser(g_parser, resumable);
4733 XML_SetDefaultHandler(g_parser, NULL);
4734 }
4735 }
4736
START_TEST(test_abort_epilog)4737 START_TEST(test_abort_epilog) {
4738 const char *text = "<doc></doc>\n\r\n";
4739 XML_Char match[] = XCS("\r");
4740
4741 XML_SetDefaultHandler(g_parser, selective_aborting_default_handler);
4742 XML_SetUserData(g_parser, match);
4743 resumable = XML_FALSE;
4744 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4745 != XML_STATUS_ERROR)
4746 fail("Abort not triggered");
4747 if (XML_GetErrorCode(g_parser) != XML_ERROR_ABORTED)
4748 xml_failure(g_parser);
4749 }
4750 END_TEST
4751
4752 /* Test a different code path for abort in the epilog */
START_TEST(test_abort_epilog_2)4753 START_TEST(test_abort_epilog_2) {
4754 const char *text = "<doc></doc>\n";
4755 XML_Char match[] = XCS("\n");
4756
4757 XML_SetDefaultHandler(g_parser, selective_aborting_default_handler);
4758 XML_SetUserData(g_parser, match);
4759 resumable = XML_FALSE;
4760 expect_failure(text, XML_ERROR_ABORTED, "Abort not triggered");
4761 }
4762 END_TEST
4763
4764 /* Test suspension from the epilog */
START_TEST(test_suspend_epilog)4765 START_TEST(test_suspend_epilog) {
4766 const char *text = "<doc></doc>\n";
4767 XML_Char match[] = XCS("\n");
4768
4769 XML_SetDefaultHandler(g_parser, selective_aborting_default_handler);
4770 XML_SetUserData(g_parser, match);
4771 resumable = XML_TRUE;
4772 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4773 != XML_STATUS_SUSPENDED)
4774 xml_failure(g_parser);
4775 }
4776 END_TEST
4777
4778 static void XMLCALL
suspending_end_handler(void * userData,const XML_Char * s)4779 suspending_end_handler(void *userData, const XML_Char *s) {
4780 UNUSED_P(s);
4781 XML_StopParser((XML_Parser)userData, 1);
4782 }
4783
START_TEST(test_suspend_in_sole_empty_tag)4784 START_TEST(test_suspend_in_sole_empty_tag) {
4785 const char *text = "<doc/>";
4786 enum XML_Status rc;
4787
4788 XML_SetEndElementHandler(g_parser, suspending_end_handler);
4789 XML_SetUserData(g_parser, g_parser);
4790 rc = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE);
4791 if (rc == XML_STATUS_ERROR)
4792 xml_failure(g_parser);
4793 else if (rc != XML_STATUS_SUSPENDED)
4794 fail("Suspend not triggered");
4795 rc = XML_ResumeParser(g_parser);
4796 if (rc == XML_STATUS_ERROR)
4797 xml_failure(g_parser);
4798 else if (rc != XML_STATUS_OK)
4799 fail("Resume failed");
4800 }
4801 END_TEST
4802
START_TEST(test_unfinished_epilog)4803 START_TEST(test_unfinished_epilog) {
4804 const char *text = "<doc></doc><";
4805
4806 expect_failure(text, XML_ERROR_UNCLOSED_TOKEN,
4807 "Incomplete epilog entry not faulted");
4808 }
4809 END_TEST
4810
START_TEST(test_partial_char_in_epilog)4811 START_TEST(test_partial_char_in_epilog) {
4812 const char *text = "<doc></doc>\xe2\x82";
4813
4814 /* First check that no fault is raised if the parse is not finished */
4815 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
4816 == XML_STATUS_ERROR)
4817 xml_failure(g_parser);
4818 /* Now check that it is faulted once we finish */
4819 if (XML_ParseBuffer(g_parser, 0, XML_TRUE) != XML_STATUS_ERROR)
4820 fail("Partial character in epilog not faulted");
4821 if (XML_GetErrorCode(g_parser) != XML_ERROR_PARTIAL_CHAR)
4822 xml_failure(g_parser);
4823 }
4824 END_TEST
4825
START_TEST(test_hash_collision)4826 START_TEST(test_hash_collision) {
4827 /* For full coverage of the lookup routine, we need to ensure a
4828 * hash collision even though we can only tell that we have one
4829 * through breakpoint debugging or coverage statistics. The
4830 * following will cause a hash collision on machines with a 64-bit
4831 * long type; others will have to experiment. The full coverage
4832 * tests invoked from qa.sh usually provide a hash collision, but
4833 * not always. This is an attempt to provide insurance.
4834 */
4835 #define COLLIDING_HASH_SALT (unsigned long)_SIP_ULL(0xffffffffU, 0xff99fc90U)
4836 const char *text
4837 = "<doc>\n"
4838 "<a1/><a2/><a3/><a4/><a5/><a6/><a7/><a8/>\n"
4839 "<b1></b1><b2 attr='foo'>This is a foo</b2><b3></b3><b4></b4>\n"
4840 "<b5></b5><b6></b6><b7></b7><b8></b8>\n"
4841 "<c1/><c2/><c3/><c4/><c5/><c6/><c7/><c8/>\n"
4842 "<d1/><d2/><d3/><d4/><d5/><d6/><d7/>\n"
4843 "<d8>This triggers the table growth and collides with b2</d8>\n"
4844 "</doc>\n";
4845
4846 XML_SetHashSalt(g_parser, COLLIDING_HASH_SALT);
4847 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4848 == XML_STATUS_ERROR)
4849 xml_failure(g_parser);
4850 }
4851 END_TEST
4852 #undef COLLIDING_HASH_SALT
4853
4854 /* Test resuming a parse suspended in entity substitution */
4855 static void XMLCALL
start_element_suspender(void * userData,const XML_Char * name,const XML_Char ** atts)4856 start_element_suspender(void *userData, const XML_Char *name,
4857 const XML_Char **atts) {
4858 UNUSED_P(userData);
4859 UNUSED_P(atts);
4860 if (! xcstrcmp(name, XCS("suspend")))
4861 XML_StopParser(g_parser, XML_TRUE);
4862 if (! xcstrcmp(name, XCS("abort")))
4863 XML_StopParser(g_parser, XML_FALSE);
4864 }
4865
START_TEST(test_suspend_resume_internal_entity)4866 START_TEST(test_suspend_resume_internal_entity) {
4867 const char *text
4868 = "<!DOCTYPE doc [\n"
4869 "<!ENTITY foo '<suspend>Hi<suspend>Ho</suspend></suspend>'>\n"
4870 "]>\n"
4871 "<doc>&foo;</doc>\n";
4872 const XML_Char *expected1 = XCS("Hi");
4873 const XML_Char *expected2 = XCS("HiHo");
4874 CharData storage;
4875
4876 CharData_Init(&storage);
4877 XML_SetStartElementHandler(g_parser, start_element_suspender);
4878 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
4879 XML_SetUserData(g_parser, &storage);
4880 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
4881 != XML_STATUS_SUSPENDED)
4882 xml_failure(g_parser);
4883 CharData_CheckXMLChars(&storage, XCS(""));
4884 if (XML_ResumeParser(g_parser) != XML_STATUS_SUSPENDED)
4885 xml_failure(g_parser);
4886 CharData_CheckXMLChars(&storage, expected1);
4887 if (XML_ResumeParser(g_parser) != XML_STATUS_OK)
4888 xml_failure(g_parser);
4889 CharData_CheckXMLChars(&storage, expected2);
4890 }
4891 END_TEST
4892
4893 /* Test syntax error is caught at parse resumption */
START_TEST(test_resume_entity_with_syntax_error)4894 START_TEST(test_resume_entity_with_syntax_error) {
4895 const char *text = "<!DOCTYPE doc [\n"
4896 "<!ENTITY foo '<suspend>Hi</wombat>'>\n"
4897 "]>\n"
4898 "<doc>&foo;</doc>\n";
4899
4900 XML_SetStartElementHandler(g_parser, start_element_suspender);
4901 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
4902 != XML_STATUS_SUSPENDED)
4903 xml_failure(g_parser);
4904 if (XML_ResumeParser(g_parser) != XML_STATUS_ERROR)
4905 fail("Syntax error in entity not faulted");
4906 if (XML_GetErrorCode(g_parser) != XML_ERROR_TAG_MISMATCH)
4907 xml_failure(g_parser);
4908 }
4909 END_TEST
4910
4911 /* Test suspending and resuming in a parameter entity substitution */
4912 static void XMLCALL
element_decl_suspender(void * userData,const XML_Char * name,XML_Content * model)4913 element_decl_suspender(void *userData, const XML_Char *name,
4914 XML_Content *model) {
4915 UNUSED_P(userData);
4916 UNUSED_P(name);
4917 XML_StopParser(g_parser, XML_TRUE);
4918 XML_FreeContentModel(g_parser, model);
4919 }
4920
START_TEST(test_suspend_resume_parameter_entity)4921 START_TEST(test_suspend_resume_parameter_entity) {
4922 const char *text = "<!DOCTYPE doc [\n"
4923 "<!ENTITY % foo '<!ELEMENT doc (#PCDATA)*>'>\n"
4924 "%foo;\n"
4925 "]>\n"
4926 "<doc>Hello, world</doc>";
4927 const XML_Char *expected = XCS("Hello, world");
4928 CharData storage;
4929
4930 CharData_Init(&storage);
4931 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4932 XML_SetElementDeclHandler(g_parser, element_decl_suspender);
4933 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
4934 XML_SetUserData(g_parser, &storage);
4935 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
4936 != XML_STATUS_SUSPENDED)
4937 xml_failure(g_parser);
4938 CharData_CheckXMLChars(&storage, XCS(""));
4939 if (XML_ResumeParser(g_parser) != XML_STATUS_OK)
4940 xml_failure(g_parser);
4941 CharData_CheckXMLChars(&storage, expected);
4942 }
4943 END_TEST
4944
4945 /* Test attempting to use parser after an error is faulted */
START_TEST(test_restart_on_error)4946 START_TEST(test_restart_on_error) {
4947 const char *text = "<$doc><doc></doc>";
4948
4949 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
4950 != XML_STATUS_ERROR)
4951 fail("Invalid tag name not faulted");
4952 if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
4953 xml_failure(g_parser);
4954 if (XML_Parse(g_parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR)
4955 fail("Restarting invalid parse not faulted");
4956 if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
4957 xml_failure(g_parser);
4958 }
4959 END_TEST
4960
4961 /* Test that angle brackets in an attribute default value are faulted */
START_TEST(test_reject_lt_in_attribute_value)4962 START_TEST(test_reject_lt_in_attribute_value) {
4963 const char *text = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '<bar>'>]>\n"
4964 "<doc></doc>";
4965
4966 expect_failure(text, XML_ERROR_INVALID_TOKEN,
4967 "Bad attribute default not faulted");
4968 }
4969 END_TEST
4970
START_TEST(test_reject_unfinished_param_in_att_value)4971 START_TEST(test_reject_unfinished_param_in_att_value) {
4972 const char *text = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '&foo'>]>\n"
4973 "<doc></doc>";
4974
4975 expect_failure(text, XML_ERROR_INVALID_TOKEN,
4976 "Bad attribute default not faulted");
4977 }
4978 END_TEST
4979
START_TEST(test_trailing_cr_in_att_value)4980 START_TEST(test_trailing_cr_in_att_value) {
4981 const char *text = "<doc a='value\r'/>";
4982
4983 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4984 == XML_STATUS_ERROR)
4985 xml_failure(g_parser);
4986 }
4987 END_TEST
4988
4989 /* Try parsing a general entity within a parameter entity in a
4990 * standalone internal DTD. Covers a corner case in the parser.
4991 */
START_TEST(test_standalone_internal_entity)4992 START_TEST(test_standalone_internal_entity) {
4993 const char *text = "<?xml version='1.0' standalone='yes' ?>\n"
4994 "<!DOCTYPE doc [\n"
4995 " <!ELEMENT doc (#PCDATA)>\n"
4996 " <!ENTITY % pe '<!ATTLIST doc att2 CDATA \"≥\">'>\n"
4997 " <!ENTITY ge 'AttDefaultValue'>\n"
4998 " %pe;\n"
4999 "]>\n"
5000 "<doc att2='any'/>";
5001
5002 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5003 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5004 == XML_STATUS_ERROR)
5005 xml_failure(g_parser);
5006 }
5007 END_TEST
5008
5009 /* Test that a reference to an unknown external entity is skipped */
START_TEST(test_skipped_external_entity)5010 START_TEST(test_skipped_external_entity) {
5011 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
5012 "<doc></doc>\n";
5013 ExtTest test_data = {"<!ELEMENT doc EMPTY>\n"
5014 "<!ENTITY % e2 '%e1;'>\n",
5015 NULL, NULL};
5016
5017 XML_SetUserData(g_parser, &test_data);
5018 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5019 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
5020 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5021 == XML_STATUS_ERROR)
5022 xml_failure(g_parser);
5023 }
5024 END_TEST
5025
5026 /* Test a different form of unknown external entity */
5027 typedef struct ext_hdlr_data {
5028 const char *parse_text;
5029 XML_ExternalEntityRefHandler handler;
5030 } ExtHdlrData;
5031
5032 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)5033 external_entity_oneshot_loader(XML_Parser parser, const XML_Char *context,
5034 const XML_Char *base, const XML_Char *systemId,
5035 const XML_Char *publicId) {
5036 ExtHdlrData *test_data = (ExtHdlrData *)XML_GetUserData(parser);
5037 XML_Parser ext_parser;
5038
5039 UNUSED_P(base);
5040 UNUSED_P(systemId);
5041 UNUSED_P(publicId);
5042 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
5043 if (ext_parser == NULL)
5044 fail("Could not create external entity parser.");
5045 /* Use the requested entity parser for further externals */
5046 XML_SetExternalEntityRefHandler(ext_parser, test_data->handler);
5047 if (_XML_Parse_SINGLE_BYTES(ext_parser, test_data->parse_text,
5048 (int)strlen(test_data->parse_text), XML_TRUE)
5049 == XML_STATUS_ERROR) {
5050 xml_failure(ext_parser);
5051 }
5052
5053 XML_ParserFree(ext_parser);
5054 return XML_STATUS_OK;
5055 }
5056
START_TEST(test_skipped_null_loaded_ext_entity)5057 START_TEST(test_skipped_null_loaded_ext_entity) {
5058 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n"
5059 "<doc />";
5060 ExtHdlrData test_data
5061 = {"<!ENTITY % pe1 SYSTEM 'http://example.org/two.ent'>\n"
5062 "<!ENTITY % pe2 '%pe1;'>\n"
5063 "%pe2;\n",
5064 external_entity_null_loader};
5065
5066 XML_SetUserData(g_parser, &test_data);
5067 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5068 XML_SetExternalEntityRefHandler(g_parser, external_entity_oneshot_loader);
5069 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5070 == XML_STATUS_ERROR)
5071 xml_failure(g_parser);
5072 }
5073 END_TEST
5074
START_TEST(test_skipped_unloaded_ext_entity)5075 START_TEST(test_skipped_unloaded_ext_entity) {
5076 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n"
5077 "<doc />";
5078 ExtHdlrData test_data
5079 = {"<!ENTITY % pe1 SYSTEM 'http://example.org/two.ent'>\n"
5080 "<!ENTITY % pe2 '%pe1;'>\n"
5081 "%pe2;\n",
5082 NULL};
5083
5084 XML_SetUserData(g_parser, &test_data);
5085 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5086 XML_SetExternalEntityRefHandler(g_parser, external_entity_oneshot_loader);
5087 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5088 == XML_STATUS_ERROR)
5089 xml_failure(g_parser);
5090 }
5091 END_TEST
5092
5093 /* Test that a parameter entity value ending with a carriage return
5094 * has it translated internally into a newline.
5095 */
START_TEST(test_param_entity_with_trailing_cr)5096 START_TEST(test_param_entity_with_trailing_cr) {
5097 #define PARAM_ENTITY_NAME "pe"
5098 #define PARAM_ENTITY_CORE_VALUE "<!ATTLIST doc att CDATA \"default\">"
5099 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
5100 "<doc/>";
5101 ExtTest test_data
5102 = {"<!ENTITY % " PARAM_ENTITY_NAME " '" PARAM_ENTITY_CORE_VALUE "\r'>\n"
5103 "%" PARAM_ENTITY_NAME ";\n",
5104 NULL, NULL};
5105
5106 XML_SetUserData(g_parser, &test_data);
5107 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5108 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
5109 XML_SetEntityDeclHandler(g_parser, param_entity_match_handler);
5110 entity_name_to_match = XCS(PARAM_ENTITY_NAME);
5111 entity_value_to_match = XCS(PARAM_ENTITY_CORE_VALUE) XCS("\n");
5112 entity_match_flag = ENTITY_MATCH_NOT_FOUND;
5113 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5114 == XML_STATUS_ERROR)
5115 xml_failure(g_parser);
5116 if (entity_match_flag == ENTITY_MATCH_FAIL)
5117 fail("Parameter entity CR->NEWLINE conversion failed");
5118 else if (entity_match_flag == ENTITY_MATCH_NOT_FOUND)
5119 fail("Parameter entity not parsed");
5120 }
5121 #undef PARAM_ENTITY_NAME
5122 #undef PARAM_ENTITY_CORE_VALUE
5123 END_TEST
5124
START_TEST(test_invalid_character_entity)5125 START_TEST(test_invalid_character_entity) {
5126 const char *text = "<!DOCTYPE doc [\n"
5127 " <!ENTITY entity '�'>\n"
5128 "]>\n"
5129 "<doc>&entity;</doc>";
5130
5131 expect_failure(text, XML_ERROR_BAD_CHAR_REF,
5132 "Out of range character reference not faulted");
5133 }
5134 END_TEST
5135
START_TEST(test_invalid_character_entity_2)5136 START_TEST(test_invalid_character_entity_2) {
5137 const char *text = "<!DOCTYPE doc [\n"
5138 " <!ENTITY entity '&#xg0;'>\n"
5139 "]>\n"
5140 "<doc>&entity;</doc>";
5141
5142 expect_failure(text, XML_ERROR_INVALID_TOKEN,
5143 "Out of range character reference not faulted");
5144 }
5145 END_TEST
5146
START_TEST(test_invalid_character_entity_3)5147 START_TEST(test_invalid_character_entity_3) {
5148 const char text[] =
5149 /* <!DOCTYPE doc [\n */
5150 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0\n"
5151 /* U+0E04 = KHO KHWAI
5152 * U+0E08 = CHO CHAN */
5153 /* <!ENTITY entity '&\u0e04\u0e08;'>\n */
5154 "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0e\0n\0t\0i\0t\0y\0 "
5155 "\0'\0&\x0e\x04\x0e\x08\0;\0'\0>\0\n"
5156 /* ]>\n */
5157 "\0]\0>\0\n"
5158 /* <doc>&entity;</doc> */
5159 "\0<\0d\0o\0c\0>\0&\0e\0n\0t\0i\0t\0y\0;\0<\0/\0d\0o\0c\0>";
5160
5161 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5162 != XML_STATUS_ERROR)
5163 fail("Invalid start of entity name not faulted");
5164 if (XML_GetErrorCode(g_parser) != XML_ERROR_UNDEFINED_ENTITY)
5165 xml_failure(g_parser);
5166 }
5167 END_TEST
5168
START_TEST(test_invalid_character_entity_4)5169 START_TEST(test_invalid_character_entity_4) {
5170 const char *text = "<!DOCTYPE doc [\n"
5171 " <!ENTITY entity '�'>\n" /* = � */
5172 "]>\n"
5173 "<doc>&entity;</doc>";
5174
5175 expect_failure(text, XML_ERROR_BAD_CHAR_REF,
5176 "Out of range character reference not faulted");
5177 }
5178 END_TEST
5179
5180 /* Test that processing instructions are picked up by a default handler */
START_TEST(test_pi_handled_in_default)5181 START_TEST(test_pi_handled_in_default) {
5182 const char *text = "<?test processing instruction?>\n<doc/>";
5183 const XML_Char *expected = XCS("<?test processing instruction?>\n<doc/>");
5184 CharData storage;
5185
5186 CharData_Init(&storage);
5187 XML_SetDefaultHandler(g_parser, accumulate_characters);
5188 XML_SetUserData(g_parser, &storage);
5189 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5190 == XML_STATUS_ERROR)
5191 xml_failure(g_parser);
5192 CharData_CheckXMLChars(&storage, expected);
5193 }
5194 END_TEST
5195
5196 /* Test that comments are picked up by a default handler */
START_TEST(test_comment_handled_in_default)5197 START_TEST(test_comment_handled_in_default) {
5198 const char *text = "<!-- This is a comment -->\n<doc/>";
5199 const XML_Char *expected = XCS("<!-- This is a comment -->\n<doc/>");
5200 CharData storage;
5201
5202 CharData_Init(&storage);
5203 XML_SetDefaultHandler(g_parser, accumulate_characters);
5204 XML_SetUserData(g_parser, &storage);
5205 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5206 == XML_STATUS_ERROR)
5207 xml_failure(g_parser);
5208 CharData_CheckXMLChars(&storage, expected);
5209 }
5210 END_TEST
5211
5212 /* Test PIs that look almost but not quite like XML declarations */
5213 static void XMLCALL
accumulate_pi_characters(void * userData,const XML_Char * target,const XML_Char * data)5214 accumulate_pi_characters(void *userData, const XML_Char *target,
5215 const XML_Char *data) {
5216 CharData *storage = (CharData *)userData;
5217
5218 CharData_AppendXMLChars(storage, target, -1);
5219 CharData_AppendXMLChars(storage, XCS(": "), 2);
5220 CharData_AppendXMLChars(storage, data, -1);
5221 CharData_AppendXMLChars(storage, XCS("\n"), 1);
5222 }
5223
START_TEST(test_pi_yml)5224 START_TEST(test_pi_yml) {
5225 const char *text = "<?yml something like data?><doc/>";
5226 const XML_Char *expected = XCS("yml: something like data\n");
5227 CharData storage;
5228
5229 CharData_Init(&storage);
5230 XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5231 XML_SetUserData(g_parser, &storage);
5232 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5233 == XML_STATUS_ERROR)
5234 xml_failure(g_parser);
5235 CharData_CheckXMLChars(&storage, expected);
5236 }
5237 END_TEST
5238
START_TEST(test_pi_xnl)5239 START_TEST(test_pi_xnl) {
5240 const char *text = "<?xnl nothing like data?><doc/>";
5241 const XML_Char *expected = XCS("xnl: nothing like data\n");
5242 CharData storage;
5243
5244 CharData_Init(&storage);
5245 XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5246 XML_SetUserData(g_parser, &storage);
5247 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5248 == XML_STATUS_ERROR)
5249 xml_failure(g_parser);
5250 CharData_CheckXMLChars(&storage, expected);
5251 }
5252 END_TEST
5253
START_TEST(test_pi_xmm)5254 START_TEST(test_pi_xmm) {
5255 const char *text = "<?xmm everything like data?><doc/>";
5256 const XML_Char *expected = XCS("xmm: everything like data\n");
5257 CharData storage;
5258
5259 CharData_Init(&storage);
5260 XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5261 XML_SetUserData(g_parser, &storage);
5262 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5263 == XML_STATUS_ERROR)
5264 xml_failure(g_parser);
5265 CharData_CheckXMLChars(&storage, expected);
5266 }
5267 END_TEST
5268
START_TEST(test_utf16_pi)5269 START_TEST(test_utf16_pi) {
5270 const char text[] =
5271 /* <?{KHO KHWAI}{CHO CHAN}?>
5272 * where {KHO KHWAI} = U+0E04
5273 * and {CHO CHAN} = U+0E08
5274 */
5275 "<\0?\0\x04\x0e\x08\x0e?\0>\0"
5276 /* <q/> */
5277 "<\0q\0/\0>\0";
5278 #ifdef XML_UNICODE
5279 const XML_Char *expected = XCS("\x0e04\x0e08: \n");
5280 #else
5281 const XML_Char *expected = XCS("\xe0\xb8\x84\xe0\xb8\x88: \n");
5282 #endif
5283 CharData storage;
5284
5285 CharData_Init(&storage);
5286 XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5287 XML_SetUserData(g_parser, &storage);
5288 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5289 == XML_STATUS_ERROR)
5290 xml_failure(g_parser);
5291 CharData_CheckXMLChars(&storage, expected);
5292 }
5293 END_TEST
5294
START_TEST(test_utf16_be_pi)5295 START_TEST(test_utf16_be_pi) {
5296 const char text[] =
5297 /* <?{KHO KHWAI}{CHO CHAN}?>
5298 * where {KHO KHWAI} = U+0E04
5299 * and {CHO CHAN} = U+0E08
5300 */
5301 "\0<\0?\x0e\x04\x0e\x08\0?\0>"
5302 /* <q/> */
5303 "\0<\0q\0/\0>";
5304 #ifdef XML_UNICODE
5305 const XML_Char *expected = XCS("\x0e04\x0e08: \n");
5306 #else
5307 const XML_Char *expected = XCS("\xe0\xb8\x84\xe0\xb8\x88: \n");
5308 #endif
5309 CharData storage;
5310
5311 CharData_Init(&storage);
5312 XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5313 XML_SetUserData(g_parser, &storage);
5314 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5315 == XML_STATUS_ERROR)
5316 xml_failure(g_parser);
5317 CharData_CheckXMLChars(&storage, expected);
5318 }
5319 END_TEST
5320
5321 /* Test that comments can be picked up and translated */
5322 static void XMLCALL
accumulate_comment(void * userData,const XML_Char * data)5323 accumulate_comment(void *userData, const XML_Char *data) {
5324 CharData *storage = (CharData *)userData;
5325
5326 CharData_AppendXMLChars(storage, data, -1);
5327 }
5328
START_TEST(test_utf16_be_comment)5329 START_TEST(test_utf16_be_comment) {
5330 const char text[] =
5331 /* <!-- Comment A --> */
5332 "\0<\0!\0-\0-\0 \0C\0o\0m\0m\0e\0n\0t\0 \0A\0 \0-\0-\0>\0\n"
5333 /* <doc/> */
5334 "\0<\0d\0o\0c\0/\0>";
5335 const XML_Char *expected = XCS(" Comment A ");
5336 CharData storage;
5337
5338 CharData_Init(&storage);
5339 XML_SetCommentHandler(g_parser, accumulate_comment);
5340 XML_SetUserData(g_parser, &storage);
5341 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5342 == XML_STATUS_ERROR)
5343 xml_failure(g_parser);
5344 CharData_CheckXMLChars(&storage, expected);
5345 }
5346 END_TEST
5347
START_TEST(test_utf16_le_comment)5348 START_TEST(test_utf16_le_comment) {
5349 const char text[] =
5350 /* <!-- Comment B --> */
5351 "<\0!\0-\0-\0 \0C\0o\0m\0m\0e\0n\0t\0 \0B\0 \0-\0-\0>\0\n\0"
5352 /* <doc/> */
5353 "<\0d\0o\0c\0/\0>\0";
5354 const XML_Char *expected = XCS(" Comment B ");
5355 CharData storage;
5356
5357 CharData_Init(&storage);
5358 XML_SetCommentHandler(g_parser, accumulate_comment);
5359 XML_SetUserData(g_parser, &storage);
5360 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5361 == XML_STATUS_ERROR)
5362 xml_failure(g_parser);
5363 CharData_CheckXMLChars(&storage, expected);
5364 }
5365 END_TEST
5366
5367 /* Test that the unknown encoding handler with map entries that expect
5368 * conversion but no conversion function is faulted
5369 */
5370 static int XMLCALL
failing_converter(void * data,const char * s)5371 failing_converter(void *data, const char *s) {
5372 UNUSED_P(data);
5373 UNUSED_P(s);
5374 /* Always claim to have failed */
5375 return -1;
5376 }
5377
5378 static int XMLCALL
prefix_converter(void * data,const char * s)5379 prefix_converter(void *data, const char *s) {
5380 UNUSED_P(data);
5381 /* If the first byte is 0xff, raise an error */
5382 if (s[0] == (char)-1)
5383 return -1;
5384 /* Just add the low bits of the first byte to the second */
5385 return (s[1] + (s[0] & 0x7f)) & 0x01ff;
5386 }
5387
5388 static int XMLCALL
MiscEncodingHandler(void * data,const XML_Char * encoding,XML_Encoding * info)5389 MiscEncodingHandler(void *data, const XML_Char *encoding, XML_Encoding *info) {
5390 int i;
5391 int high_map = -2; /* Assume a 2-byte sequence */
5392
5393 if (! xcstrcmp(encoding, XCS("invalid-9"))
5394 || ! xcstrcmp(encoding, XCS("ascii-like"))
5395 || ! xcstrcmp(encoding, XCS("invalid-len"))
5396 || ! xcstrcmp(encoding, XCS("invalid-a"))
5397 || ! xcstrcmp(encoding, XCS("invalid-surrogate"))
5398 || ! xcstrcmp(encoding, XCS("invalid-high")))
5399 high_map = -1;
5400
5401 for (i = 0; i < 128; ++i)
5402 info->map[i] = i;
5403 for (; i < 256; ++i)
5404 info->map[i] = high_map;
5405
5406 /* If required, put an invalid value in the ASCII entries */
5407 if (! xcstrcmp(encoding, XCS("invalid-9")))
5408 info->map[9] = 5;
5409 /* If required, have a top-bit set character starts a 5-byte sequence */
5410 if (! xcstrcmp(encoding, XCS("invalid-len")))
5411 info->map[0x81] = -5;
5412 /* If required, make a top-bit set character a valid ASCII character */
5413 if (! xcstrcmp(encoding, XCS("invalid-a")))
5414 info->map[0x82] = 'a';
5415 /* If required, give a top-bit set character a forbidden value,
5416 * what would otherwise be the first of a surrogate pair.
5417 */
5418 if (! xcstrcmp(encoding, XCS("invalid-surrogate")))
5419 info->map[0x83] = 0xd801;
5420 /* If required, give a top-bit set character too high a value */
5421 if (! xcstrcmp(encoding, XCS("invalid-high")))
5422 info->map[0x84] = 0x010101;
5423
5424 info->data = data;
5425 info->release = NULL;
5426 if (! xcstrcmp(encoding, XCS("failing-conv")))
5427 info->convert = failing_converter;
5428 else if (! xcstrcmp(encoding, XCS("prefix-conv")))
5429 info->convert = prefix_converter;
5430 else
5431 info->convert = NULL;
5432 return XML_STATUS_OK;
5433 }
5434
START_TEST(test_missing_encoding_conversion_fn)5435 START_TEST(test_missing_encoding_conversion_fn) {
5436 const char *text = "<?xml version='1.0' encoding='no-conv'?>\n"
5437 "<doc>\x81</doc>";
5438
5439 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5440 /* MiscEncodingHandler sets up an encoding with every top-bit-set
5441 * character introducing a two-byte sequence. For this, it
5442 * requires a convert function. The above function call doesn't
5443 * pass one through, so when BadEncodingHandler actually gets
5444 * called it should supply an invalid encoding.
5445 */
5446 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5447 "Encoding with missing convert() not faulted");
5448 }
5449 END_TEST
5450
START_TEST(test_failing_encoding_conversion_fn)5451 START_TEST(test_failing_encoding_conversion_fn) {
5452 const char *text = "<?xml version='1.0' encoding='failing-conv'?>\n"
5453 "<doc>\x81</doc>";
5454
5455 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5456 /* BadEncodingHandler sets up an encoding with every top-bit-set
5457 * character introducing a two-byte sequence. For this, it
5458 * requires a convert function. The above function call passes
5459 * one that insists all possible sequences are invalid anyway.
5460 */
5461 expect_failure(text, XML_ERROR_INVALID_TOKEN,
5462 "Encoding with failing convert() not faulted");
5463 }
5464 END_TEST
5465
5466 /* Test unknown encoding conversions */
START_TEST(test_unknown_encoding_success)5467 START_TEST(test_unknown_encoding_success) {
5468 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5469 /* Equivalent to <eoc>Hello, world</eoc> */
5470 "<\x81\x64\x80oc>Hello, world</\x81\x64\x80oc>";
5471
5472 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5473 run_character_check(text, XCS("Hello, world"));
5474 }
5475 END_TEST
5476
5477 /* Test bad name character in unknown encoding */
START_TEST(test_unknown_encoding_bad_name)5478 START_TEST(test_unknown_encoding_bad_name) {
5479 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5480 "<\xff\x64oc>Hello, world</\xff\x64oc>";
5481
5482 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5483 expect_failure(text, XML_ERROR_INVALID_TOKEN,
5484 "Bad name start in unknown encoding not faulted");
5485 }
5486 END_TEST
5487
5488 /* Test bad mid-name character in unknown encoding */
START_TEST(test_unknown_encoding_bad_name_2)5489 START_TEST(test_unknown_encoding_bad_name_2) {
5490 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5491 "<d\xffoc>Hello, world</d\xffoc>";
5492
5493 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5494 expect_failure(text, XML_ERROR_INVALID_TOKEN,
5495 "Bad name in unknown encoding not faulted");
5496 }
5497 END_TEST
5498
5499 /* Test element name that is long enough to fill the conversion buffer
5500 * in an unknown encoding, finishing with an encoded character.
5501 */
START_TEST(test_unknown_encoding_long_name_1)5502 START_TEST(test_unknown_encoding_long_name_1) {
5503 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5504 "<abcdefghabcdefghabcdefghijkl\x80m\x80n\x80o\x80p>"
5505 "Hi"
5506 "</abcdefghabcdefghabcdefghijkl\x80m\x80n\x80o\x80p>";
5507 const XML_Char *expected = XCS("abcdefghabcdefghabcdefghijklmnop");
5508 CharData storage;
5509
5510 CharData_Init(&storage);
5511 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5512 XML_SetStartElementHandler(g_parser, record_element_start_handler);
5513 XML_SetUserData(g_parser, &storage);
5514 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5515 == XML_STATUS_ERROR)
5516 xml_failure(g_parser);
5517 CharData_CheckXMLChars(&storage, expected);
5518 }
5519 END_TEST
5520
5521 /* Test element name that is long enough to fill the conversion buffer
5522 * in an unknown encoding, finishing with an simple character.
5523 */
START_TEST(test_unknown_encoding_long_name_2)5524 START_TEST(test_unknown_encoding_long_name_2) {
5525 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5526 "<abcdefghabcdefghabcdefghijklmnop>"
5527 "Hi"
5528 "</abcdefghabcdefghabcdefghijklmnop>";
5529 const XML_Char *expected = XCS("abcdefghabcdefghabcdefghijklmnop");
5530 CharData storage;
5531
5532 CharData_Init(&storage);
5533 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5534 XML_SetStartElementHandler(g_parser, record_element_start_handler);
5535 XML_SetUserData(g_parser, &storage);
5536 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5537 == XML_STATUS_ERROR)
5538 xml_failure(g_parser);
5539 CharData_CheckXMLChars(&storage, expected);
5540 }
5541 END_TEST
5542
START_TEST(test_invalid_unknown_encoding)5543 START_TEST(test_invalid_unknown_encoding) {
5544 const char *text = "<?xml version='1.0' encoding='invalid-9'?>\n"
5545 "<doc>Hello world</doc>";
5546
5547 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5548 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5549 "Invalid unknown encoding not faulted");
5550 }
5551 END_TEST
5552
START_TEST(test_unknown_ascii_encoding_ok)5553 START_TEST(test_unknown_ascii_encoding_ok) {
5554 const char *text = "<?xml version='1.0' encoding='ascii-like'?>\n"
5555 "<doc>Hello, world</doc>";
5556
5557 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5558 run_character_check(text, XCS("Hello, world"));
5559 }
5560 END_TEST
5561
START_TEST(test_unknown_ascii_encoding_fail)5562 START_TEST(test_unknown_ascii_encoding_fail) {
5563 const char *text = "<?xml version='1.0' encoding='ascii-like'?>\n"
5564 "<doc>Hello, \x80 world</doc>";
5565
5566 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5567 expect_failure(text, XML_ERROR_INVALID_TOKEN,
5568 "Invalid character not faulted");
5569 }
5570 END_TEST
5571
START_TEST(test_unknown_encoding_invalid_length)5572 START_TEST(test_unknown_encoding_invalid_length) {
5573 const char *text = "<?xml version='1.0' encoding='invalid-len'?>\n"
5574 "<doc>Hello, world</doc>";
5575
5576 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5577 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5578 "Invalid unknown encoding not faulted");
5579 }
5580 END_TEST
5581
START_TEST(test_unknown_encoding_invalid_topbit)5582 START_TEST(test_unknown_encoding_invalid_topbit) {
5583 const char *text = "<?xml version='1.0' encoding='invalid-a'?>\n"
5584 "<doc>Hello, world</doc>";
5585
5586 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5587 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5588 "Invalid unknown encoding not faulted");
5589 }
5590 END_TEST
5591
START_TEST(test_unknown_encoding_invalid_surrogate)5592 START_TEST(test_unknown_encoding_invalid_surrogate) {
5593 const char *text = "<?xml version='1.0' encoding='invalid-surrogate'?>\n"
5594 "<doc>Hello, \x82 world</doc>";
5595
5596 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5597 expect_failure(text, XML_ERROR_INVALID_TOKEN,
5598 "Invalid unknown encoding not faulted");
5599 }
5600 END_TEST
5601
START_TEST(test_unknown_encoding_invalid_high)5602 START_TEST(test_unknown_encoding_invalid_high) {
5603 const char *text = "<?xml version='1.0' encoding='invalid-high'?>\n"
5604 "<doc>Hello, world</doc>";
5605
5606 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5607 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5608 "Invalid unknown encoding not faulted");
5609 }
5610 END_TEST
5611
START_TEST(test_unknown_encoding_invalid_attr_value)5612 START_TEST(test_unknown_encoding_invalid_attr_value) {
5613 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5614 "<doc attr='\xff\x30'/>";
5615
5616 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5617 expect_failure(text, XML_ERROR_INVALID_TOKEN,
5618 "Invalid attribute valid not faulted");
5619 }
5620 END_TEST
5621
5622 /* Test an external entity parser set to use latin-1 detects UTF-16
5623 * BOMs correctly.
5624 */
5625 enum ee_parse_flags { EE_PARSE_NONE = 0x00, EE_PARSE_FULL_BUFFER = 0x01 };
5626
5627 typedef struct ExtTest2 {
5628 const char *parse_text;
5629 int parse_len;
5630 const XML_Char *encoding;
5631 CharData *storage;
5632 enum ee_parse_flags flags;
5633 } ExtTest2;
5634
5635 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)5636 external_entity_loader2(XML_Parser parser, const XML_Char *context,
5637 const XML_Char *base, const XML_Char *systemId,
5638 const XML_Char *publicId) {
5639 ExtTest2 *test_data = (ExtTest2 *)XML_GetUserData(parser);
5640 XML_Parser extparser;
5641
5642 UNUSED_P(base);
5643 UNUSED_P(systemId);
5644 UNUSED_P(publicId);
5645 extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
5646 if (extparser == NULL)
5647 fail("Coulr not create external entity parser");
5648 if (test_data->encoding != NULL) {
5649 if (! XML_SetEncoding(extparser, test_data->encoding))
5650 fail("XML_SetEncoding() ignored for external entity");
5651 }
5652 if (test_data->flags & EE_PARSE_FULL_BUFFER) {
5653 if (XML_Parse(extparser, test_data->parse_text, test_data->parse_len,
5654 XML_TRUE)
5655 == XML_STATUS_ERROR) {
5656 xml_failure(extparser);
5657 }
5658 } else if (_XML_Parse_SINGLE_BYTES(extparser, test_data->parse_text,
5659 test_data->parse_len, XML_TRUE)
5660 == XML_STATUS_ERROR) {
5661 xml_failure(extparser);
5662 }
5663
5664 XML_ParserFree(extparser);
5665 return XML_STATUS_OK;
5666 }
5667
5668 /* Test that UTF-16 BOM does not select UTF-16 given explicit encoding */
5669 static void XMLCALL
ext2_accumulate_characters(void * userData,const XML_Char * s,int len)5670 ext2_accumulate_characters(void *userData, const XML_Char *s, int len) {
5671 ExtTest2 *test_data = (ExtTest2 *)userData;
5672 accumulate_characters(test_data->storage, s, len);
5673 }
5674
START_TEST(test_ext_entity_latin1_utf16le_bom)5675 START_TEST(test_ext_entity_latin1_utf16le_bom) {
5676 const char *text = "<!DOCTYPE doc [\n"
5677 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5678 "]>\n"
5679 "<doc>&en;</doc>";
5680 ExtTest2 test_data
5681 = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */
5682 /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn,
5683 * 0x4c = L and 0x20 is a space
5684 */
5685 "\xff\xfe\x4c\x20", 4, XCS("iso-8859-1"), NULL, EE_PARSE_NONE};
5686 #ifdef XML_UNICODE
5687 const XML_Char *expected = XCS("\x00ff\x00feL ");
5688 #else
5689 /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */
5690 const XML_Char *expected = XCS("\xc3\xbf\xc3\xbeL ");
5691 #endif
5692 CharData storage;
5693
5694 CharData_Init(&storage);
5695 test_data.storage = &storage;
5696 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5697 XML_SetUserData(g_parser, &test_data);
5698 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5699 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5700 == XML_STATUS_ERROR)
5701 xml_failure(g_parser);
5702 CharData_CheckXMLChars(&storage, expected);
5703 }
5704 END_TEST
5705
START_TEST(test_ext_entity_latin1_utf16be_bom)5706 START_TEST(test_ext_entity_latin1_utf16be_bom) {
5707 const char *text = "<!DOCTYPE doc [\n"
5708 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5709 "]>\n"
5710 "<doc>&en;</doc>";
5711 ExtTest2 test_data
5712 = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */
5713 /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn,
5714 * 0x4c = L and 0x20 is a space
5715 */
5716 "\xfe\xff\x20\x4c", 4, XCS("iso-8859-1"), NULL, EE_PARSE_NONE};
5717 #ifdef XML_UNICODE
5718 const XML_Char *expected = XCS("\x00fe\x00ff L");
5719 #else
5720 /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */
5721 const XML_Char *expected = XCS("\xc3\xbe\xc3\xbf L");
5722 #endif
5723 CharData storage;
5724
5725 CharData_Init(&storage);
5726 test_data.storage = &storage;
5727 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5728 XML_SetUserData(g_parser, &test_data);
5729 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5730 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5731 == XML_STATUS_ERROR)
5732 xml_failure(g_parser);
5733 CharData_CheckXMLChars(&storage, expected);
5734 }
5735 END_TEST
5736
5737 /* Parsing the full buffer rather than a byte at a time makes a
5738 * difference to the encoding scanning code, so repeat the above tests
5739 * without breaking them down by byte.
5740 */
START_TEST(test_ext_entity_latin1_utf16le_bom2)5741 START_TEST(test_ext_entity_latin1_utf16le_bom2) {
5742 const char *text = "<!DOCTYPE doc [\n"
5743 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5744 "]>\n"
5745 "<doc>&en;</doc>";
5746 ExtTest2 test_data
5747 = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */
5748 /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn,
5749 * 0x4c = L and 0x20 is a space
5750 */
5751 "\xff\xfe\x4c\x20", 4, XCS("iso-8859-1"), NULL, EE_PARSE_FULL_BUFFER};
5752 #ifdef XML_UNICODE
5753 const XML_Char *expected = XCS("\x00ff\x00feL ");
5754 #else
5755 /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */
5756 const XML_Char *expected = XCS("\xc3\xbf\xc3\xbeL ");
5757 #endif
5758 CharData storage;
5759
5760 CharData_Init(&storage);
5761 test_data.storage = &storage;
5762 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5763 XML_SetUserData(g_parser, &test_data);
5764 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5765 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
5766 == XML_STATUS_ERROR)
5767 xml_failure(g_parser);
5768 CharData_CheckXMLChars(&storage, expected);
5769 }
5770 END_TEST
5771
START_TEST(test_ext_entity_latin1_utf16be_bom2)5772 START_TEST(test_ext_entity_latin1_utf16be_bom2) {
5773 const char *text = "<!DOCTYPE doc [\n"
5774 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5775 "]>\n"
5776 "<doc>&en;</doc>";
5777 ExtTest2 test_data
5778 = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */
5779 /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn,
5780 * 0x4c = L and 0x20 is a space
5781 */
5782 "\xfe\xff\x20\x4c", 4, XCS("iso-8859-1"), NULL, EE_PARSE_FULL_BUFFER};
5783 #ifdef XML_UNICODE
5784 const XML_Char *expected = XCS("\x00fe\x00ff L");
5785 #else
5786 /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */
5787 const XML_Char *expected = "\xc3\xbe\xc3\xbf L";
5788 #endif
5789 CharData storage;
5790
5791 CharData_Init(&storage);
5792 test_data.storage = &storage;
5793 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5794 XML_SetUserData(g_parser, &test_data);
5795 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5796 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
5797 == XML_STATUS_ERROR)
5798 xml_failure(g_parser);
5799 CharData_CheckXMLChars(&storage, expected);
5800 }
5801 END_TEST
5802
5803 /* Test little-endian UTF-16 given an explicit big-endian encoding */
START_TEST(test_ext_entity_utf16_be)5804 START_TEST(test_ext_entity_utf16_be) {
5805 const char *text = "<!DOCTYPE doc [\n"
5806 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5807 "]>\n"
5808 "<doc>&en;</doc>";
5809 ExtTest2 test_data
5810 = {"<\0e\0/\0>\0", 8, XCS("utf-16be"), NULL, EE_PARSE_NONE};
5811 #ifdef XML_UNICODE
5812 const XML_Char *expected = XCS("\x3c00\x6500\x2f00\x3e00");
5813 #else
5814 const XML_Char *expected = XCS("\xe3\xb0\x80" /* U+3C00 */
5815 "\xe6\x94\x80" /* U+6500 */
5816 "\xe2\xbc\x80" /* U+2F00 */
5817 "\xe3\xb8\x80"); /* U+3E00 */
5818 #endif
5819 CharData storage;
5820
5821 CharData_Init(&storage);
5822 test_data.storage = &storage;
5823 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5824 XML_SetUserData(g_parser, &test_data);
5825 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5826 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5827 == XML_STATUS_ERROR)
5828 xml_failure(g_parser);
5829 CharData_CheckXMLChars(&storage, expected);
5830 }
5831 END_TEST
5832
5833 /* Test big-endian UTF-16 given an explicit little-endian encoding */
START_TEST(test_ext_entity_utf16_le)5834 START_TEST(test_ext_entity_utf16_le) {
5835 const char *text = "<!DOCTYPE doc [\n"
5836 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5837 "]>\n"
5838 "<doc>&en;</doc>";
5839 ExtTest2 test_data
5840 = {"\0<\0e\0/\0>", 8, XCS("utf-16le"), NULL, EE_PARSE_NONE};
5841 #ifdef XML_UNICODE
5842 const XML_Char *expected = XCS("\x3c00\x6500\x2f00\x3e00");
5843 #else
5844 const XML_Char *expected = XCS("\xe3\xb0\x80" /* U+3C00 */
5845 "\xe6\x94\x80" /* U+6500 */
5846 "\xe2\xbc\x80" /* U+2F00 */
5847 "\xe3\xb8\x80"); /* U+3E00 */
5848 #endif
5849 CharData storage;
5850
5851 CharData_Init(&storage);
5852 test_data.storage = &storage;
5853 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5854 XML_SetUserData(g_parser, &test_data);
5855 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5856 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5857 == XML_STATUS_ERROR)
5858 xml_failure(g_parser);
5859 CharData_CheckXMLChars(&storage, expected);
5860 }
5861 END_TEST
5862
5863 /* Test little-endian UTF-16 given no explicit encoding.
5864 * The existing default encoding (UTF-8) is assumed to hold without a
5865 * BOM to contradict it, so the entity value will in fact provoke an
5866 * error because 0x00 is not a valid XML character. We parse the
5867 * whole buffer in one go rather than feeding it in byte by byte to
5868 * exercise different code paths in the initial scanning routines.
5869 */
5870 typedef struct ExtFaults2 {
5871 const char *parse_text;
5872 int parse_len;
5873 const char *fail_text;
5874 const XML_Char *encoding;
5875 enum XML_Error error;
5876 } ExtFaults2;
5877
5878 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)5879 external_entity_faulter2(XML_Parser parser, const XML_Char *context,
5880 const XML_Char *base, const XML_Char *systemId,
5881 const XML_Char *publicId) {
5882 ExtFaults2 *test_data = (ExtFaults2 *)XML_GetUserData(parser);
5883 XML_Parser extparser;
5884
5885 UNUSED_P(base);
5886 UNUSED_P(systemId);
5887 UNUSED_P(publicId);
5888 extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
5889 if (extparser == NULL)
5890 fail("Could not create external entity parser");
5891 if (test_data->encoding != NULL) {
5892 if (! XML_SetEncoding(extparser, test_data->encoding))
5893 fail("XML_SetEncoding() ignored for external entity");
5894 }
5895 if (XML_Parse(extparser, test_data->parse_text, test_data->parse_len,
5896 XML_TRUE)
5897 != XML_STATUS_ERROR)
5898 fail(test_data->fail_text);
5899 if (XML_GetErrorCode(extparser) != test_data->error)
5900 xml_failure(extparser);
5901
5902 XML_ParserFree(extparser);
5903 return XML_STATUS_ERROR;
5904 }
5905
START_TEST(test_ext_entity_utf16_unknown)5906 START_TEST(test_ext_entity_utf16_unknown) {
5907 const char *text = "<!DOCTYPE doc [\n"
5908 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5909 "]>\n"
5910 "<doc>&en;</doc>";
5911 ExtFaults2 test_data
5912 = {"a\0b\0c\0", 6, "Invalid character in entity not faulted", NULL,
5913 XML_ERROR_INVALID_TOKEN};
5914
5915 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter2);
5916 XML_SetUserData(g_parser, &test_data);
5917 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
5918 "Invalid character should not have been accepted");
5919 }
5920 END_TEST
5921
5922 /* Test not-quite-UTF-8 BOM (0xEF 0xBB 0xBF) */
START_TEST(test_ext_entity_utf8_non_bom)5923 START_TEST(test_ext_entity_utf8_non_bom) {
5924 const char *text = "<!DOCTYPE doc [\n"
5925 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5926 "]>\n"
5927 "<doc>&en;</doc>";
5928 ExtTest2 test_data
5929 = {"\xef\xbb\x80", /* Arabic letter DAD medial form, U+FEC0 */
5930 3, NULL, NULL, EE_PARSE_NONE};
5931 #ifdef XML_UNICODE
5932 const XML_Char *expected = XCS("\xfec0");
5933 #else
5934 const XML_Char *expected = XCS("\xef\xbb\x80");
5935 #endif
5936 CharData storage;
5937
5938 CharData_Init(&storage);
5939 test_data.storage = &storage;
5940 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5941 XML_SetUserData(g_parser, &test_data);
5942 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5943 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5944 == XML_STATUS_ERROR)
5945 xml_failure(g_parser);
5946 CharData_CheckXMLChars(&storage, expected);
5947 }
5948 END_TEST
5949
5950 /* Test that UTF-8 in a CDATA section is correctly passed through */
START_TEST(test_utf8_in_cdata_section)5951 START_TEST(test_utf8_in_cdata_section) {
5952 const char *text = "<doc><![CDATA[one \xc3\xa9 two]]></doc>";
5953 #ifdef XML_UNICODE
5954 const XML_Char *expected = XCS("one \x00e9 two");
5955 #else
5956 const XML_Char *expected = XCS("one \xc3\xa9 two");
5957 #endif
5958
5959 run_character_check(text, expected);
5960 }
5961 END_TEST
5962
5963 /* Test that little-endian UTF-16 in a CDATA section is handled */
START_TEST(test_utf8_in_cdata_section_2)5964 START_TEST(test_utf8_in_cdata_section_2) {
5965 const char *text = "<doc><![CDATA[\xc3\xa9]\xc3\xa9two]]></doc>";
5966 #ifdef XML_UNICODE
5967 const XML_Char *expected = XCS("\x00e9]\x00e9two");
5968 #else
5969 const XML_Char *expected = XCS("\xc3\xa9]\xc3\xa9two");
5970 #endif
5971
5972 run_character_check(text, expected);
5973 }
5974 END_TEST
5975
5976 /* Test trailing spaces in elements are accepted */
5977 static void XMLCALL
record_element_end_handler(void * userData,const XML_Char * name)5978 record_element_end_handler(void *userData, const XML_Char *name) {
5979 CharData *storage = (CharData *)userData;
5980
5981 CharData_AppendXMLChars(storage, XCS("/"), 1);
5982 CharData_AppendXMLChars(storage, name, -1);
5983 }
5984
START_TEST(test_trailing_spaces_in_elements)5985 START_TEST(test_trailing_spaces_in_elements) {
5986 const char *text = "<doc >Hi</doc >";
5987 const XML_Char *expected = XCS("doc/doc");
5988 CharData storage;
5989
5990 CharData_Init(&storage);
5991 XML_SetElementHandler(g_parser, record_element_start_handler,
5992 record_element_end_handler);
5993 XML_SetUserData(g_parser, &storage);
5994 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5995 == XML_STATUS_ERROR)
5996 xml_failure(g_parser);
5997 CharData_CheckXMLChars(&storage, expected);
5998 }
5999 END_TEST
6000
START_TEST(test_utf16_attribute)6001 START_TEST(test_utf16_attribute) {
6002 const char text[] =
6003 /* <d {KHO KHWAI}{CHO CHAN}='a'/>
6004 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
6005 * and {CHO CHAN} = U+0E08 = 0xe0 0xb8 0x88 in UTF-8
6006 */
6007 "<\0d\0 \0\x04\x0e\x08\x0e=\0'\0a\0'\0/\0>\0";
6008 const XML_Char *expected = XCS("a");
6009 CharData storage;
6010
6011 CharData_Init(&storage);
6012 XML_SetStartElementHandler(g_parser, accumulate_attribute);
6013 XML_SetUserData(g_parser, &storage);
6014 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6015 == XML_STATUS_ERROR)
6016 xml_failure(g_parser);
6017 CharData_CheckXMLChars(&storage, expected);
6018 }
6019 END_TEST
6020
START_TEST(test_utf16_second_attr)6021 START_TEST(test_utf16_second_attr) {
6022 /* <d a='1' {KHO KHWAI}{CHO CHAN}='2'/>
6023 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
6024 * and {CHO CHAN} = U+0E08 = 0xe0 0xb8 0x88 in UTF-8
6025 */
6026 const char text[] = "<\0d\0 \0a\0=\0'\0\x31\0'\0 \0"
6027 "\x04\x0e\x08\x0e=\0'\0\x32\0'\0/\0>\0";
6028 const XML_Char *expected = XCS("1");
6029 CharData storage;
6030
6031 CharData_Init(&storage);
6032 XML_SetStartElementHandler(g_parser, accumulate_attribute);
6033 XML_SetUserData(g_parser, &storage);
6034 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6035 == XML_STATUS_ERROR)
6036 xml_failure(g_parser);
6037 CharData_CheckXMLChars(&storage, expected);
6038 }
6039 END_TEST
6040
START_TEST(test_attr_after_solidus)6041 START_TEST(test_attr_after_solidus) {
6042 const char *text = "<doc attr1='a' / attr2='b'>";
6043
6044 expect_failure(text, XML_ERROR_INVALID_TOKEN, "Misplaced / not faulted");
6045 }
6046 END_TEST
6047
6048 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)6049 accumulate_entity_decl(void *userData, const XML_Char *entityName,
6050 int is_parameter_entity, const XML_Char *value,
6051 int value_length, const XML_Char *base,
6052 const XML_Char *systemId, const XML_Char *publicId,
6053 const XML_Char *notationName) {
6054 CharData *storage = (CharData *)userData;
6055
6056 UNUSED_P(is_parameter_entity);
6057 UNUSED_P(base);
6058 UNUSED_P(systemId);
6059 UNUSED_P(publicId);
6060 UNUSED_P(notationName);
6061 CharData_AppendXMLChars(storage, entityName, -1);
6062 CharData_AppendXMLChars(storage, XCS("="), 1);
6063 CharData_AppendXMLChars(storage, value, value_length);
6064 CharData_AppendXMLChars(storage, XCS("\n"), 1);
6065 }
6066
START_TEST(test_utf16_pe)6067 START_TEST(test_utf16_pe) {
6068 /* <!DOCTYPE doc [
6069 * <!ENTITY % {KHO KHWAI}{CHO CHAN} '<!ELEMENT doc (#PCDATA)>'>
6070 * %{KHO KHWAI}{CHO CHAN};
6071 * ]>
6072 * <doc></doc>
6073 *
6074 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
6075 * and {CHO CHAN} = U+0E08 = 0xe0 0xb8 0x88 in UTF-8
6076 */
6077 const char text[] = "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0\n"
6078 "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \x0e\x04\x0e\x08\0 "
6079 "\0'\0<\0!\0E\0L\0E\0M\0E\0N\0T\0 "
6080 "\0d\0o\0c\0 \0(\0#\0P\0C\0D\0A\0T\0A\0)\0>\0'\0>\0\n"
6081 "\0%\x0e\x04\x0e\x08\0;\0\n"
6082 "\0]\0>\0\n"
6083 "\0<\0d\0o\0c\0>\0<\0/\0d\0o\0c\0>";
6084 #ifdef XML_UNICODE
6085 const XML_Char *expected = XCS("\x0e04\x0e08=<!ELEMENT doc (#PCDATA)>\n");
6086 #else
6087 const XML_Char *expected
6088 = XCS("\xe0\xb8\x84\xe0\xb8\x88=<!ELEMENT doc (#PCDATA)>\n");
6089 #endif
6090 CharData storage;
6091
6092 CharData_Init(&storage);
6093 XML_SetUserData(g_parser, &storage);
6094 XML_SetEntityDeclHandler(g_parser, accumulate_entity_decl);
6095 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6096 == XML_STATUS_ERROR)
6097 xml_failure(g_parser);
6098 CharData_CheckXMLChars(&storage, expected);
6099 }
6100 END_TEST
6101
6102 /* Test that duff attribute description keywords are rejected */
START_TEST(test_bad_attr_desc_keyword)6103 START_TEST(test_bad_attr_desc_keyword) {
6104 const char *text = "<!DOCTYPE doc [\n"
6105 " <!ATTLIST doc attr CDATA #!IMPLIED>\n"
6106 "]>\n"
6107 "<doc />";
6108
6109 expect_failure(text, XML_ERROR_INVALID_TOKEN,
6110 "Bad keyword !IMPLIED not faulted");
6111 }
6112 END_TEST
6113
6114 /* Test that an invalid attribute description keyword consisting of
6115 * UTF-16 characters with their top bytes non-zero are correctly
6116 * faulted
6117 */
START_TEST(test_bad_attr_desc_keyword_utf16)6118 START_TEST(test_bad_attr_desc_keyword_utf16) {
6119 /* <!DOCTYPE d [
6120 * <!ATTLIST d a CDATA #{KHO KHWAI}{CHO CHAN}>
6121 * ]><d/>
6122 *
6123 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
6124 * and {CHO CHAN} = U+0E08 = 0xe0 0xb8 0x88 in UTF-8
6125 */
6126 const char text[]
6127 = "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n"
6128 "\0<\0!\0A\0T\0T\0L\0I\0S\0T\0 \0d\0 \0a\0 \0C\0D\0A\0T\0A\0 "
6129 "\0#\x0e\x04\x0e\x08\0>\0\n"
6130 "\0]\0>\0<\0d\0/\0>";
6131
6132 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6133 != XML_STATUS_ERROR)
6134 fail("Invalid UTF16 attribute keyword not faulted");
6135 if (XML_GetErrorCode(g_parser) != XML_ERROR_SYNTAX)
6136 xml_failure(g_parser);
6137 }
6138 END_TEST
6139
6140 /* Test that invalid syntax in a <!DOCTYPE> is rejected. Do this
6141 * using prefix-encoding (see above) to trigger specific code paths
6142 */
START_TEST(test_bad_doctype)6143 START_TEST(test_bad_doctype) {
6144 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
6145 "<!DOCTYPE doc [ \x80\x44 ]><doc/>";
6146
6147 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
6148 expect_failure(text, XML_ERROR_SYNTAX,
6149 "Invalid bytes in DOCTYPE not faulted");
6150 }
6151 END_TEST
6152
START_TEST(test_bad_doctype_utf16)6153 START_TEST(test_bad_doctype_utf16) {
6154 const char text[] =
6155 /* <!DOCTYPE doc [ \x06f2 ]><doc/>
6156 *
6157 * U+06F2 = EXTENDED ARABIC-INDIC DIGIT TWO, a valid number
6158 * (name character) but not a valid letter (name start character)
6159 */
6160 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0 "
6161 "\x06\xf2"
6162 "\0 \0]\0>\0<\0d\0o\0c\0/\0>";
6163
6164 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6165 != XML_STATUS_ERROR)
6166 fail("Invalid bytes in DOCTYPE not faulted");
6167 if (XML_GetErrorCode(g_parser) != XML_ERROR_SYNTAX)
6168 xml_failure(g_parser);
6169 }
6170 END_TEST
6171
START_TEST(test_bad_doctype_plus)6172 START_TEST(test_bad_doctype_plus) {
6173 const char *text = "<!DOCTYPE 1+ [ <!ENTITY foo 'bar'> ]>\n"
6174 "<1+>&foo;</1+>";
6175
6176 expect_failure(text, XML_ERROR_INVALID_TOKEN,
6177 "'+' in document name not faulted");
6178 }
6179 END_TEST
6180
START_TEST(test_bad_doctype_star)6181 START_TEST(test_bad_doctype_star) {
6182 const char *text = "<!DOCTYPE 1* [ <!ENTITY foo 'bar'> ]>\n"
6183 "<1*>&foo;</1*>";
6184
6185 expect_failure(text, XML_ERROR_INVALID_TOKEN,
6186 "'*' in document name not faulted");
6187 }
6188 END_TEST
6189
START_TEST(test_bad_doctype_query)6190 START_TEST(test_bad_doctype_query) {
6191 const char *text = "<!DOCTYPE 1? [ <!ENTITY foo 'bar'> ]>\n"
6192 "<1?>&foo;</1?>";
6193
6194 expect_failure(text, XML_ERROR_INVALID_TOKEN,
6195 "'?' in document name not faulted");
6196 }
6197 END_TEST
6198
START_TEST(test_unknown_encoding_bad_ignore)6199 START_TEST(test_unknown_encoding_bad_ignore) {
6200 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>"
6201 "<!DOCTYPE doc SYSTEM 'foo'>"
6202 "<doc><e>&entity;</e></doc>";
6203 ExtFaults fault = {"<![IGNORE[<!ELEMENT \xffG (#PCDATA)*>]]>",
6204 "Invalid character not faulted", XCS("prefix-conv"),
6205 XML_ERROR_INVALID_TOKEN};
6206
6207 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
6208 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6209 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
6210 XML_SetUserData(g_parser, &fault);
6211 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
6212 "Bad IGNORE section with unknown encoding not failed");
6213 }
6214 END_TEST
6215
START_TEST(test_entity_in_utf16_be_attr)6216 START_TEST(test_entity_in_utf16_be_attr) {
6217 const char text[] =
6218 /* <e a='ä ä'></e> */
6219 "\0<\0e\0 \0a\0=\0'\0&\0#\0\x32\0\x32\0\x38\0;\0 "
6220 "\0&\0#\0x\0\x30\0\x30\0E\0\x34\0;\0'\0>\0<\0/\0e\0>";
6221 #ifdef XML_UNICODE
6222 const XML_Char *expected = XCS("\x00e4 \x00e4");
6223 #else
6224 const XML_Char *expected = XCS("\xc3\xa4 \xc3\xa4");
6225 #endif
6226 CharData storage;
6227
6228 CharData_Init(&storage);
6229 XML_SetUserData(g_parser, &storage);
6230 XML_SetStartElementHandler(g_parser, accumulate_attribute);
6231 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6232 == XML_STATUS_ERROR)
6233 xml_failure(g_parser);
6234 CharData_CheckXMLChars(&storage, expected);
6235 }
6236 END_TEST
6237
START_TEST(test_entity_in_utf16_le_attr)6238 START_TEST(test_entity_in_utf16_le_attr) {
6239 const char text[] =
6240 /* <e a='ä ä'></e> */
6241 "<\0e\0 \0a\0=\0'\0&\0#\0\x32\0\x32\0\x38\0;\0 \0"
6242 "&\0#\0x\0\x30\0\x30\0E\0\x34\0;\0'\0>\0<\0/\0e\0>\0";
6243 #ifdef XML_UNICODE
6244 const XML_Char *expected = XCS("\x00e4 \x00e4");
6245 #else
6246 const XML_Char *expected = XCS("\xc3\xa4 \xc3\xa4");
6247 #endif
6248 CharData storage;
6249
6250 CharData_Init(&storage);
6251 XML_SetUserData(g_parser, &storage);
6252 XML_SetStartElementHandler(g_parser, accumulate_attribute);
6253 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6254 == XML_STATUS_ERROR)
6255 xml_failure(g_parser);
6256 CharData_CheckXMLChars(&storage, expected);
6257 }
6258 END_TEST
6259
START_TEST(test_entity_public_utf16_be)6260 START_TEST(test_entity_public_utf16_be) {
6261 const char text[] =
6262 /* <!DOCTYPE d [ */
6263 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n"
6264 /* <!ENTITY % e PUBLIC 'foo' 'bar.ent'> */
6265 "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \0e\0 \0P\0U\0B\0L\0I\0C\0 "
6266 "\0'\0f\0o\0o\0'\0 \0'\0b\0a\0r\0.\0e\0n\0t\0'\0>\0\n"
6267 /* %e; */
6268 "\0%\0e\0;\0\n"
6269 /* ]> */
6270 "\0]\0>\0\n"
6271 /* <d>&j;</d> */
6272 "\0<\0d\0>\0&\0j\0;\0<\0/\0d\0>";
6273 ExtTest2 test_data = {/* <!ENTITY j 'baz'> */
6274 "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0j\0 \0'\0b\0a\0z\0'\0>",
6275 34, NULL, NULL, EE_PARSE_NONE};
6276 const XML_Char *expected = XCS("baz");
6277 CharData storage;
6278
6279 CharData_Init(&storage);
6280 test_data.storage = &storage;
6281 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6282 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
6283 XML_SetUserData(g_parser, &test_data);
6284 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
6285 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6286 == XML_STATUS_ERROR)
6287 xml_failure(g_parser);
6288 CharData_CheckXMLChars(&storage, expected);
6289 }
6290 END_TEST
6291
START_TEST(test_entity_public_utf16_le)6292 START_TEST(test_entity_public_utf16_le) {
6293 const char text[] =
6294 /* <!DOCTYPE d [ */
6295 "<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n\0"
6296 /* <!ENTITY % e PUBLIC 'foo' 'bar.ent'> */
6297 "<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \0e\0 \0P\0U\0B\0L\0I\0C\0 \0"
6298 "'\0f\0o\0o\0'\0 \0'\0b\0a\0r\0.\0e\0n\0t\0'\0>\0\n\0"
6299 /* %e; */
6300 "%\0e\0;\0\n\0"
6301 /* ]> */
6302 "]\0>\0\n\0"
6303 /* <d>&j;</d> */
6304 "<\0d\0>\0&\0j\0;\0<\0/\0d\0>\0";
6305 ExtTest2 test_data = {/* <!ENTITY j 'baz'> */
6306 "<\0!\0E\0N\0T\0I\0T\0Y\0 \0j\0 \0'\0b\0a\0z\0'\0>\0",
6307 34, NULL, NULL, EE_PARSE_NONE};
6308 const XML_Char *expected = XCS("baz");
6309 CharData storage;
6310
6311 CharData_Init(&storage);
6312 test_data.storage = &storage;
6313 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6314 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
6315 XML_SetUserData(g_parser, &test_data);
6316 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
6317 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6318 == XML_STATUS_ERROR)
6319 xml_failure(g_parser);
6320 CharData_CheckXMLChars(&storage, expected);
6321 }
6322 END_TEST
6323
6324 /* Test that a doctype with neither an internal nor external subset is
6325 * faulted
6326 */
START_TEST(test_short_doctype)6327 START_TEST(test_short_doctype) {
6328 const char *text = "<!DOCTYPE doc></doc>";
6329 expect_failure(text, XML_ERROR_INVALID_TOKEN,
6330 "DOCTYPE without subset not rejected");
6331 }
6332 END_TEST
6333
START_TEST(test_short_doctype_2)6334 START_TEST(test_short_doctype_2) {
6335 const char *text = "<!DOCTYPE doc PUBLIC></doc>";
6336 expect_failure(text, XML_ERROR_SYNTAX,
6337 "DOCTYPE without Public ID not rejected");
6338 }
6339 END_TEST
6340
START_TEST(test_short_doctype_3)6341 START_TEST(test_short_doctype_3) {
6342 const char *text = "<!DOCTYPE doc SYSTEM></doc>";
6343 expect_failure(text, XML_ERROR_SYNTAX,
6344 "DOCTYPE without System ID not rejected");
6345 }
6346 END_TEST
6347
START_TEST(test_long_doctype)6348 START_TEST(test_long_doctype) {
6349 const char *text = "<!DOCTYPE doc PUBLIC 'foo' 'bar' 'baz'></doc>";
6350 expect_failure(text, XML_ERROR_SYNTAX, "DOCTYPE with extra ID not rejected");
6351 }
6352 END_TEST
6353
START_TEST(test_bad_entity)6354 START_TEST(test_bad_entity) {
6355 const char *text = "<!DOCTYPE doc [\n"
6356 " <!ENTITY foo PUBLIC>\n"
6357 "]>\n"
6358 "<doc/>";
6359 expect_failure(text, XML_ERROR_SYNTAX,
6360 "ENTITY without Public ID is not rejected");
6361 }
6362 END_TEST
6363
6364 /* Test unquoted value is faulted */
START_TEST(test_bad_entity_2)6365 START_TEST(test_bad_entity_2) {
6366 const char *text = "<!DOCTYPE doc [\n"
6367 " <!ENTITY % foo bar>\n"
6368 "]>\n"
6369 "<doc/>";
6370 expect_failure(text, XML_ERROR_SYNTAX,
6371 "ENTITY without Public ID is not rejected");
6372 }
6373 END_TEST
6374
START_TEST(test_bad_entity_3)6375 START_TEST(test_bad_entity_3) {
6376 const char *text = "<!DOCTYPE doc [\n"
6377 " <!ENTITY % foo PUBLIC>\n"
6378 "]>\n"
6379 "<doc/>";
6380 expect_failure(text, XML_ERROR_SYNTAX,
6381 "Parameter ENTITY without Public ID is not rejected");
6382 }
6383 END_TEST
6384
START_TEST(test_bad_entity_4)6385 START_TEST(test_bad_entity_4) {
6386 const char *text = "<!DOCTYPE doc [\n"
6387 " <!ENTITY % foo SYSTEM>\n"
6388 "]>\n"
6389 "<doc/>";
6390 expect_failure(text, XML_ERROR_SYNTAX,
6391 "Parameter ENTITY without Public ID is not rejected");
6392 }
6393 END_TEST
6394
START_TEST(test_bad_notation)6395 START_TEST(test_bad_notation) {
6396 const char *text = "<!DOCTYPE doc [\n"
6397 " <!NOTATION n SYSTEM>\n"
6398 "]>\n"
6399 "<doc/>";
6400 expect_failure(text, XML_ERROR_SYNTAX,
6401 "Notation without System ID is not rejected");
6402 }
6403 END_TEST
6404
6405 /* Test for issue #11, wrongly suppressed default handler */
6406 typedef struct default_check {
6407 const XML_Char *expected;
6408 const int expectedLen;
6409 XML_Bool seen;
6410 } DefaultCheck;
6411
6412 static void XMLCALL
checking_default_handler(void * userData,const XML_Char * s,int len)6413 checking_default_handler(void *userData, const XML_Char *s, int len) {
6414 DefaultCheck *data = (DefaultCheck *)userData;
6415 int i;
6416
6417 for (i = 0; data[i].expected != NULL; i++) {
6418 if (data[i].expectedLen == len
6419 && ! memcmp(data[i].expected, s, len * sizeof(XML_Char))) {
6420 data[i].seen = XML_TRUE;
6421 break;
6422 }
6423 }
6424 }
6425
START_TEST(test_default_doctype_handler)6426 START_TEST(test_default_doctype_handler) {
6427 const char *text = "<!DOCTYPE doc PUBLIC 'pubname' 'test.dtd' [\n"
6428 " <!ENTITY foo 'bar'>\n"
6429 "]>\n"
6430 "<doc>&foo;</doc>";
6431 DefaultCheck test_data[] = {{XCS("'pubname'"), 9, XML_FALSE},
6432 {XCS("'test.dtd'"), 10, XML_FALSE},
6433 {NULL, 0, XML_FALSE}};
6434 int i;
6435
6436 XML_SetUserData(g_parser, &test_data);
6437 XML_SetDefaultHandler(g_parser, checking_default_handler);
6438 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
6439 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6440 == XML_STATUS_ERROR)
6441 xml_failure(g_parser);
6442 for (i = 0; test_data[i].expected != NULL; i++)
6443 if (! test_data[i].seen)
6444 fail("Default handler not run for public !DOCTYPE");
6445 }
6446 END_TEST
6447
START_TEST(test_empty_element_abort)6448 START_TEST(test_empty_element_abort) {
6449 const char *text = "<abort/>";
6450
6451 XML_SetStartElementHandler(g_parser, start_element_suspender);
6452 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6453 != XML_STATUS_ERROR)
6454 fail("Expected to error on abort");
6455 }
6456 END_TEST
6457
6458 /*
6459 * Namespaces tests.
6460 */
6461
6462 static void
namespace_setup(void)6463 namespace_setup(void) {
6464 g_parser = XML_ParserCreateNS(NULL, XCS(' '));
6465 if (g_parser == NULL)
6466 fail("Parser not created.");
6467 }
6468
6469 static void
namespace_teardown(void)6470 namespace_teardown(void) {
6471 basic_teardown();
6472 }
6473
6474 /* Check that an element name and attribute name match the expected values.
6475 The expected values are passed as an array reference of string pointers
6476 provided as the userData argument; the first is the expected
6477 element name, and the second is the expected attribute name.
6478 */
6479 static int triplet_start_flag = XML_FALSE;
6480 static int triplet_end_flag = XML_FALSE;
6481
6482 static void XMLCALL
triplet_start_checker(void * userData,const XML_Char * name,const XML_Char ** atts)6483 triplet_start_checker(void *userData, const XML_Char *name,
6484 const XML_Char **atts) {
6485 XML_Char **elemstr = (XML_Char **)userData;
6486 char buffer[1024];
6487 if (xcstrcmp(elemstr[0], name) != 0) {
6488 sprintf(buffer, "unexpected start string: '%" XML_FMT_STR "'", name);
6489 fail(buffer);
6490 }
6491 if (xcstrcmp(elemstr[1], atts[0]) != 0) {
6492 sprintf(buffer, "unexpected attribute string: '%" XML_FMT_STR "'", atts[0]);
6493 fail(buffer);
6494 }
6495 triplet_start_flag = XML_TRUE;
6496 }
6497
6498 /* Check that the element name passed to the end-element handler matches
6499 the expected value. The expected value is passed as the first element
6500 in an array of strings passed as the userData argument.
6501 */
6502 static void XMLCALL
triplet_end_checker(void * userData,const XML_Char * name)6503 triplet_end_checker(void *userData, const XML_Char *name) {
6504 XML_Char **elemstr = (XML_Char **)userData;
6505 if (xcstrcmp(elemstr[0], name) != 0) {
6506 char buffer[1024];
6507 sprintf(buffer, "unexpected end string: '%" XML_FMT_STR "'", name);
6508 fail(buffer);
6509 }
6510 triplet_end_flag = XML_TRUE;
6511 }
6512
START_TEST(test_return_ns_triplet)6513 START_TEST(test_return_ns_triplet) {
6514 const char *text = "<foo:e xmlns:foo='http://example.org/' bar:a='12'\n"
6515 " xmlns:bar='http://example.org/'>";
6516 const char *epilog = "</foo:e>";
6517 const XML_Char *elemstr[]
6518 = {XCS("http://example.org/ e foo"), XCS("http://example.org/ a bar")};
6519 XML_SetReturnNSTriplet(g_parser, XML_TRUE);
6520 XML_SetUserData(g_parser, (void *)elemstr);
6521 XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
6522 XML_SetNamespaceDeclHandler(g_parser, dummy_start_namespace_decl_handler,
6523 dummy_end_namespace_decl_handler);
6524 triplet_start_flag = XML_FALSE;
6525 triplet_end_flag = XML_FALSE;
6526 dummy_handler_flags = 0;
6527 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
6528 == XML_STATUS_ERROR)
6529 xml_failure(g_parser);
6530 if (! triplet_start_flag)
6531 fail("triplet_start_checker not invoked");
6532 /* Check that unsetting "return triplets" fails while still parsing */
6533 XML_SetReturnNSTriplet(g_parser, XML_FALSE);
6534 if (_XML_Parse_SINGLE_BYTES(g_parser, epilog, (int)strlen(epilog), XML_TRUE)
6535 == XML_STATUS_ERROR)
6536 xml_failure(g_parser);
6537 if (! triplet_end_flag)
6538 fail("triplet_end_checker not invoked");
6539 if (dummy_handler_flags
6540 != (DUMMY_START_NS_DECL_HANDLER_FLAG | DUMMY_END_NS_DECL_HANDLER_FLAG))
6541 fail("Namespace handlers not called");
6542 }
6543 END_TEST
6544
6545 static void XMLCALL
overwrite_start_checker(void * userData,const XML_Char * name,const XML_Char ** atts)6546 overwrite_start_checker(void *userData, const XML_Char *name,
6547 const XML_Char **atts) {
6548 CharData *storage = (CharData *)userData;
6549 CharData_AppendXMLChars(storage, XCS("start "), 6);
6550 CharData_AppendXMLChars(storage, name, -1);
6551 while (*atts != NULL) {
6552 CharData_AppendXMLChars(storage, XCS("\nattribute "), 11);
6553 CharData_AppendXMLChars(storage, *atts, -1);
6554 atts += 2;
6555 }
6556 CharData_AppendXMLChars(storage, XCS("\n"), 1);
6557 }
6558
6559 static void XMLCALL
overwrite_end_checker(void * userData,const XML_Char * name)6560 overwrite_end_checker(void *userData, const XML_Char *name) {
6561 CharData *storage = (CharData *)userData;
6562 CharData_AppendXMLChars(storage, XCS("end "), 4);
6563 CharData_AppendXMLChars(storage, name, -1);
6564 CharData_AppendXMLChars(storage, XCS("\n"), 1);
6565 }
6566
6567 static void
run_ns_tagname_overwrite_test(const char * text,const XML_Char * result)6568 run_ns_tagname_overwrite_test(const char *text, const XML_Char *result) {
6569 CharData storage;
6570 CharData_Init(&storage);
6571 XML_SetUserData(g_parser, &storage);
6572 XML_SetElementHandler(g_parser, overwrite_start_checker,
6573 overwrite_end_checker);
6574 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6575 == XML_STATUS_ERROR)
6576 xml_failure(g_parser);
6577 CharData_CheckXMLChars(&storage, result);
6578 }
6579
6580 /* Regression test for SF bug #566334. */
START_TEST(test_ns_tagname_overwrite)6581 START_TEST(test_ns_tagname_overwrite) {
6582 const char *text = "<n:e xmlns:n='http://example.org/'>\n"
6583 " <n:f n:attr='foo'/>\n"
6584 " <n:g n:attr2='bar'/>\n"
6585 "</n:e>";
6586 const XML_Char *result = XCS("start http://example.org/ e\n")
6587 XCS("start http://example.org/ f\n")
6588 XCS("attribute http://example.org/ attr\n")
6589 XCS("end http://example.org/ f\n")
6590 XCS("start http://example.org/ g\n")
6591 XCS("attribute http://example.org/ attr2\n")
6592 XCS("end http://example.org/ g\n")
6593 XCS("end http://example.org/ e\n");
6594 run_ns_tagname_overwrite_test(text, result);
6595 }
6596 END_TEST
6597
6598 /* Regression test for SF bug #566334. */
START_TEST(test_ns_tagname_overwrite_triplet)6599 START_TEST(test_ns_tagname_overwrite_triplet) {
6600 const char *text = "<n:e xmlns:n='http://example.org/'>\n"
6601 " <n:f n:attr='foo'/>\n"
6602 " <n:g n:attr2='bar'/>\n"
6603 "</n:e>";
6604 const XML_Char *result = XCS("start http://example.org/ e n\n")
6605 XCS("start http://example.org/ f n\n")
6606 XCS("attribute http://example.org/ attr n\n")
6607 XCS("end http://example.org/ f n\n")
6608 XCS("start http://example.org/ g n\n")
6609 XCS("attribute http://example.org/ attr2 n\n")
6610 XCS("end http://example.org/ g n\n")
6611 XCS("end http://example.org/ e n\n");
6612 XML_SetReturnNSTriplet(g_parser, XML_TRUE);
6613 run_ns_tagname_overwrite_test(text, result);
6614 }
6615 END_TEST
6616
6617 /* Regression test for SF bug #620343. */
6618 static void XMLCALL
start_element_fail(void * userData,const XML_Char * name,const XML_Char ** atts)6619 start_element_fail(void *userData, const XML_Char *name,
6620 const XML_Char **atts) {
6621 UNUSED_P(userData);
6622 UNUSED_P(name);
6623 UNUSED_P(atts);
6624
6625 /* We should never get here. */
6626 fail("should never reach start_element_fail()");
6627 }
6628
6629 static void XMLCALL
start_ns_clearing_start_element(void * userData,const XML_Char * prefix,const XML_Char * uri)6630 start_ns_clearing_start_element(void *userData, const XML_Char *prefix,
6631 const XML_Char *uri) {
6632 UNUSED_P(prefix);
6633 UNUSED_P(uri);
6634 XML_SetStartElementHandler((XML_Parser)userData, NULL);
6635 }
6636
START_TEST(test_start_ns_clears_start_element)6637 START_TEST(test_start_ns_clears_start_element) {
6638 /* This needs to use separate start/end tags; using the empty tag
6639 syntax doesn't cause the problematic path through Expat to be
6640 taken.
6641 */
6642 const char *text = "<e xmlns='http://example.org/'></e>";
6643
6644 XML_SetStartElementHandler(g_parser, start_element_fail);
6645 XML_SetStartNamespaceDeclHandler(g_parser, start_ns_clearing_start_element);
6646 XML_SetEndNamespaceDeclHandler(g_parser, dummy_end_namespace_decl_handler);
6647 XML_UseParserAsHandlerArg(g_parser);
6648 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6649 == XML_STATUS_ERROR)
6650 xml_failure(g_parser);
6651 }
6652 END_TEST
6653
6654 /* Regression test for SF bug #616863. */
6655 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)6656 external_entity_handler(XML_Parser parser, const XML_Char *context,
6657 const XML_Char *base, const XML_Char *systemId,
6658 const XML_Char *publicId) {
6659 intptr_t callno = 1 + (intptr_t)XML_GetUserData(parser);
6660 const char *text;
6661 XML_Parser p2;
6662
6663 UNUSED_P(base);
6664 UNUSED_P(systemId);
6665 UNUSED_P(publicId);
6666 if (callno == 1)
6667 text = ("<!ELEMENT doc (e+)>\n"
6668 "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
6669 "<!ELEMENT e EMPTY>\n");
6670 else
6671 text = ("<?xml version='1.0' encoding='us-ascii'?>"
6672 "<e/>");
6673
6674 XML_SetUserData(parser, (void *)callno);
6675 p2 = XML_ExternalEntityParserCreate(parser, context, NULL);
6676 if (_XML_Parse_SINGLE_BYTES(p2, text, (int)strlen(text), XML_TRUE)
6677 == XML_STATUS_ERROR) {
6678 xml_failure(p2);
6679 return XML_STATUS_ERROR;
6680 }
6681 XML_ParserFree(p2);
6682 return XML_STATUS_OK;
6683 }
6684
START_TEST(test_default_ns_from_ext_subset_and_ext_ge)6685 START_TEST(test_default_ns_from_ext_subset_and_ext_ge) {
6686 const char *text = "<?xml version='1.0'?>\n"
6687 "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n"
6688 " <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n"
6689 "]>\n"
6690 "<doc xmlns='http://example.org/ns1'>\n"
6691 "&en;\n"
6692 "</doc>";
6693
6694 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6695 XML_SetExternalEntityRefHandler(g_parser, external_entity_handler);
6696 /* We actually need to set this handler to tickle this bug. */
6697 XML_SetStartElementHandler(g_parser, dummy_start_element);
6698 XML_SetUserData(g_parser, NULL);
6699 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6700 == XML_STATUS_ERROR)
6701 xml_failure(g_parser);
6702 }
6703 END_TEST
6704
6705 /* Regression test #1 for SF bug #673791. */
START_TEST(test_ns_prefix_with_empty_uri_1)6706 START_TEST(test_ns_prefix_with_empty_uri_1) {
6707 const char *text = "<doc xmlns:prefix='http://example.org/'>\n"
6708 " <e xmlns:prefix=''/>\n"
6709 "</doc>";
6710
6711 expect_failure(text, XML_ERROR_UNDECLARING_PREFIX,
6712 "Did not report re-setting namespace"
6713 " URI with prefix to ''.");
6714 }
6715 END_TEST
6716
6717 /* Regression test #2 for SF bug #673791. */
START_TEST(test_ns_prefix_with_empty_uri_2)6718 START_TEST(test_ns_prefix_with_empty_uri_2) {
6719 const char *text = "<?xml version='1.0'?>\n"
6720 "<docelem xmlns:pre=''/>";
6721
6722 expect_failure(text, XML_ERROR_UNDECLARING_PREFIX,
6723 "Did not report setting namespace URI with prefix to ''.");
6724 }
6725 END_TEST
6726
6727 /* Regression test #3 for SF bug #673791. */
START_TEST(test_ns_prefix_with_empty_uri_3)6728 START_TEST(test_ns_prefix_with_empty_uri_3) {
6729 const char *text = "<!DOCTYPE doc [\n"
6730 " <!ELEMENT doc EMPTY>\n"
6731 " <!ATTLIST doc\n"
6732 " xmlns:prefix CDATA ''>\n"
6733 "]>\n"
6734 "<doc/>";
6735
6736 expect_failure(text, XML_ERROR_UNDECLARING_PREFIX,
6737 "Didn't report attr default setting NS w/ prefix to ''.");
6738 }
6739 END_TEST
6740
6741 /* Regression test #4 for SF bug #673791. */
START_TEST(test_ns_prefix_with_empty_uri_4)6742 START_TEST(test_ns_prefix_with_empty_uri_4) {
6743 const char *text = "<!DOCTYPE doc [\n"
6744 " <!ELEMENT prefix:doc EMPTY>\n"
6745 " <!ATTLIST prefix:doc\n"
6746 " xmlns:prefix CDATA 'http://example.org/'>\n"
6747 "]>\n"
6748 "<prefix:doc/>";
6749 /* Packaged info expected by the end element handler;
6750 the weird structuring lets us re-use the triplet_end_checker()
6751 function also used for another test. */
6752 const XML_Char *elemstr[] = {XCS("http://example.org/ doc prefix")};
6753 XML_SetReturnNSTriplet(g_parser, XML_TRUE);
6754 XML_SetUserData(g_parser, (void *)elemstr);
6755 XML_SetEndElementHandler(g_parser, triplet_end_checker);
6756 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6757 == XML_STATUS_ERROR)
6758 xml_failure(g_parser);
6759 }
6760 END_TEST
6761
6762 /* Test with non-xmlns prefix */
START_TEST(test_ns_unbound_prefix)6763 START_TEST(test_ns_unbound_prefix) {
6764 const char *text = "<!DOCTYPE doc [\n"
6765 " <!ELEMENT prefix:doc EMPTY>\n"
6766 " <!ATTLIST prefix:doc\n"
6767 " notxmlns:prefix CDATA 'http://example.org/'>\n"
6768 "]>\n"
6769 "<prefix:doc/>";
6770
6771 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6772 != XML_STATUS_ERROR)
6773 fail("Unbound prefix incorrectly passed");
6774 if (XML_GetErrorCode(g_parser) != XML_ERROR_UNBOUND_PREFIX)
6775 xml_failure(g_parser);
6776 }
6777 END_TEST
6778
START_TEST(test_ns_default_with_empty_uri)6779 START_TEST(test_ns_default_with_empty_uri) {
6780 const char *text = "<doc xmlns='http://example.org/'>\n"
6781 " <e xmlns=''/>\n"
6782 "</doc>";
6783 /* Add some handlers to exercise extra code paths */
6784 XML_SetStartNamespaceDeclHandler(g_parser,
6785 dummy_start_namespace_decl_handler);
6786 XML_SetEndNamespaceDeclHandler(g_parser, dummy_end_namespace_decl_handler);
6787 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6788 == XML_STATUS_ERROR)
6789 xml_failure(g_parser);
6790 }
6791 END_TEST
6792
6793 /* Regression test for SF bug #692964: two prefixes for one namespace. */
START_TEST(test_ns_duplicate_attrs_diff_prefixes)6794 START_TEST(test_ns_duplicate_attrs_diff_prefixes) {
6795 const char *text = "<doc xmlns:a='http://example.org/a'\n"
6796 " xmlns:b='http://example.org/a'\n"
6797 " a:a='v' b:a='v' />";
6798 expect_failure(text, XML_ERROR_DUPLICATE_ATTRIBUTE,
6799 "did not report multiple attributes with same URI+name");
6800 }
6801 END_TEST
6802
START_TEST(test_ns_duplicate_hashes)6803 START_TEST(test_ns_duplicate_hashes) {
6804 /* The hash of an attribute is calculated as the hash of its URI
6805 * concatenated with a space followed by its name (after the
6806 * colon). We wish to generate attributes with the same hash
6807 * value modulo the attribute table size so that we can check that
6808 * the attribute hash table works correctly. The attribute hash
6809 * table size will be the smallest power of two greater than the
6810 * number of attributes, but at least eight. There is
6811 * unfortunately no programmatic way of getting the hash or the
6812 * table size at user level, but the test code coverage percentage
6813 * will drop if the hashes cease to point to the same row.
6814 *
6815 * The cunning plan is to have few enough attributes to have a
6816 * reliable table size of 8, and have the single letter attribute
6817 * names be 8 characters apart, producing a hash which will be the
6818 * same modulo 8.
6819 */
6820 const char *text = "<doc xmlns:a='http://example.org/a'\n"
6821 " a:a='v' a:i='w' />";
6822 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6823 == XML_STATUS_ERROR)
6824 xml_failure(g_parser);
6825 }
6826 END_TEST
6827
6828 /* Regression test for SF bug #695401: unbound prefix. */
START_TEST(test_ns_unbound_prefix_on_attribute)6829 START_TEST(test_ns_unbound_prefix_on_attribute) {
6830 const char *text = "<doc a:attr=''/>";
6831 expect_failure(text, XML_ERROR_UNBOUND_PREFIX,
6832 "did not report unbound prefix on attribute");
6833 }
6834 END_TEST
6835
6836 /* Regression test for SF bug #695401: unbound prefix. */
START_TEST(test_ns_unbound_prefix_on_element)6837 START_TEST(test_ns_unbound_prefix_on_element) {
6838 const char *text = "<a:doc/>";
6839 expect_failure(text, XML_ERROR_UNBOUND_PREFIX,
6840 "did not report unbound prefix on element");
6841 }
6842 END_TEST
6843
6844 /* Test that the parsing status is correctly reset by XML_ParserReset().
6845 * We usE test_return_ns_triplet() for our example parse to improve
6846 * coverage of tidying up code executed.
6847 */
START_TEST(test_ns_parser_reset)6848 START_TEST(test_ns_parser_reset) {
6849 XML_ParsingStatus status;
6850
6851 XML_GetParsingStatus(g_parser, &status);
6852 if (status.parsing != XML_INITIALIZED)
6853 fail("parsing status doesn't start INITIALIZED");
6854 test_return_ns_triplet();
6855 XML_GetParsingStatus(g_parser, &status);
6856 if (status.parsing != XML_FINISHED)
6857 fail("parsing status doesn't end FINISHED");
6858 XML_ParserReset(g_parser, NULL);
6859 XML_GetParsingStatus(g_parser, &status);
6860 if (status.parsing != XML_INITIALIZED)
6861 fail("parsing status doesn't reset to INITIALIZED");
6862 }
6863 END_TEST
6864
6865 /* Test that long element names with namespaces are handled correctly */
START_TEST(test_ns_long_element)6866 START_TEST(test_ns_long_element) {
6867 const char *text
6868 = "<foo:thisisalongenoughelementnametotriggerareallocation\n"
6869 " xmlns:foo='http://example.org/' bar:a='12'\n"
6870 " xmlns:bar='http://example.org/'>"
6871 "</foo:thisisalongenoughelementnametotriggerareallocation>";
6872 const XML_Char *elemstr[]
6873 = {XCS("http://example.org/")
6874 XCS(" thisisalongenoughelementnametotriggerareallocation foo"),
6875 XCS("http://example.org/ a bar")};
6876
6877 XML_SetReturnNSTriplet(g_parser, XML_TRUE);
6878 XML_SetUserData(g_parser, (void *)elemstr);
6879 XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
6880 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6881 == XML_STATUS_ERROR)
6882 xml_failure(g_parser);
6883 }
6884 END_TEST
6885
6886 /* Test mixed population of prefixed and unprefixed attributes */
START_TEST(test_ns_mixed_prefix_atts)6887 START_TEST(test_ns_mixed_prefix_atts) {
6888 const char *text = "<e a='12' bar:b='13'\n"
6889 " xmlns:bar='http://example.org/'>"
6890 "</e>";
6891
6892 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6893 == XML_STATUS_ERROR)
6894 xml_failure(g_parser);
6895 }
6896 END_TEST
6897
6898 /* Test having a long namespaced element name inside a short one.
6899 * This exercises some internal buffer reallocation that is shared
6900 * across elements with the same namespace URI.
6901 */
START_TEST(test_ns_extend_uri_buffer)6902 START_TEST(test_ns_extend_uri_buffer) {
6903 const char *text = "<foo:e xmlns:foo='http://example.org/'>"
6904 " <foo:thisisalongenoughnametotriggerallocationaction"
6905 " foo:a='12' />"
6906 "</foo:e>";
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 /* Test that xmlns is correctly rejected as an attribute in the xmlns
6914 * namespace, but not in other namespaces
6915 */
START_TEST(test_ns_reserved_attributes)6916 START_TEST(test_ns_reserved_attributes) {
6917 const char *text1
6918 = "<foo:e xmlns:foo='http://example.org/' xmlns:xmlns='12' />";
6919 const char *text2
6920 = "<foo:e xmlns:foo='http://example.org/' foo:xmlns='12' />";
6921 expect_failure(text1, XML_ERROR_RESERVED_PREFIX_XMLNS,
6922 "xmlns not rejected as an attribute");
6923 XML_ParserReset(g_parser, NULL);
6924 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
6925 == XML_STATUS_ERROR)
6926 xml_failure(g_parser);
6927 }
6928 END_TEST
6929
6930 /* Test more reserved attributes */
START_TEST(test_ns_reserved_attributes_2)6931 START_TEST(test_ns_reserved_attributes_2) {
6932 const char *text1 = "<foo:e xmlns:foo='http://example.org/'"
6933 " xmlns:xml='http://example.org/' />";
6934 const char *text2
6935 = "<foo:e xmlns:foo='http://www.w3.org/XML/1998/namespace' />";
6936 const char *text3 = "<foo:e xmlns:foo='http://www.w3.org/2000/xmlns/' />";
6937
6938 expect_failure(text1, XML_ERROR_RESERVED_PREFIX_XML,
6939 "xml not rejected as an attribute");
6940 XML_ParserReset(g_parser, NULL);
6941 expect_failure(text2, XML_ERROR_RESERVED_NAMESPACE_URI,
6942 "Use of w3.org URL not faulted");
6943 XML_ParserReset(g_parser, NULL);
6944 expect_failure(text3, XML_ERROR_RESERVED_NAMESPACE_URI,
6945 "Use of w3.org xmlns URL not faulted");
6946 }
6947 END_TEST
6948
6949 /* Test string pool handling of namespace names of 2048 characters */
6950 /* Exercises a particular string pool growth path */
START_TEST(test_ns_extremely_long_prefix)6951 START_TEST(test_ns_extremely_long_prefix) {
6952 /* C99 compilers are only required to support 4095-character
6953 * strings, so the following needs to be split in two to be safe
6954 * for all compilers.
6955 */
6956 const char *text1
6957 = "<doc "
6958 /* 64 character on each line */
6959 /* ...gives a total length of 2048 */
6960 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6961 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6962 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6963 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6964 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6965 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6966 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6967 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6968 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6969 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6970 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6971 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6972 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6973 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6974 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6975 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6976 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6977 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6978 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6979 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6980 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6981 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6982 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6983 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6984 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6985 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6986 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6987 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6988 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6989 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6990 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6991 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6992 ":a='12'";
6993 const char *text2
6994 = " xmlns:"
6995 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6996 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6997 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6998 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6999 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7000 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7001 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7002 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7003 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7004 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7005 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7006 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7007 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7008 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7009 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7010 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7011 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7012 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7013 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7014 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7015 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7016 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7017 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7018 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7019 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7020 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7021 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7022 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7023 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7024 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7025 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7026 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7027 "='foo'\n>"
7028 "</doc>";
7029
7030 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
7031 == XML_STATUS_ERROR)
7032 xml_failure(g_parser);
7033 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
7034 == XML_STATUS_ERROR)
7035 xml_failure(g_parser);
7036 }
7037 END_TEST
7038
7039 /* Test unknown encoding handlers in namespace setup */
START_TEST(test_ns_unknown_encoding_success)7040 START_TEST(test_ns_unknown_encoding_success) {
7041 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
7042 "<foo:e xmlns:foo='http://example.org/'>Hi</foo:e>";
7043
7044 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
7045 run_character_check(text, XCS("Hi"));
7046 }
7047 END_TEST
7048
7049 /* Test that too many colons are rejected */
START_TEST(test_ns_double_colon)7050 START_TEST(test_ns_double_colon) {
7051 const char *text = "<foo:e xmlns:foo='http://example.org/' foo:a:b='bar' />";
7052
7053 expect_failure(text, XML_ERROR_INVALID_TOKEN,
7054 "Double colon in attribute name not faulted");
7055 }
7056 END_TEST
7057
START_TEST(test_ns_double_colon_element)7058 START_TEST(test_ns_double_colon_element) {
7059 const char *text = "<foo:bar:e xmlns:foo='http://example.org/' />";
7060
7061 expect_failure(text, XML_ERROR_INVALID_TOKEN,
7062 "Double colon in element name not faulted");
7063 }
7064 END_TEST
7065
7066 /* Test that non-name characters after a colon are rejected */
START_TEST(test_ns_bad_attr_leafname)7067 START_TEST(test_ns_bad_attr_leafname) {
7068 const char *text = "<foo:e xmlns:foo='http://example.org/' foo:?ar='baz' />";
7069
7070 expect_failure(text, XML_ERROR_INVALID_TOKEN,
7071 "Invalid character in leafname not faulted");
7072 }
7073 END_TEST
7074
START_TEST(test_ns_bad_element_leafname)7075 START_TEST(test_ns_bad_element_leafname) {
7076 const char *text = "<foo:?oc xmlns:foo='http://example.org/' />";
7077
7078 expect_failure(text, XML_ERROR_INVALID_TOKEN,
7079 "Invalid character in element leafname not faulted");
7080 }
7081 END_TEST
7082
7083 /* Test high-byte-set UTF-16 characters are valid in a leafname */
START_TEST(test_ns_utf16_leafname)7084 START_TEST(test_ns_utf16_leafname) {
7085 const char text[] =
7086 /* <n:e xmlns:n='URI' n:{KHO KHWAI}='a' />
7087 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
7088 */
7089 "<\0n\0:\0e\0 \0x\0m\0l\0n\0s\0:\0n\0=\0'\0U\0R\0I\0'\0 \0"
7090 "n\0:\0\x04\x0e=\0'\0a\0'\0 \0/\0>\0";
7091 const XML_Char *expected = XCS("a");
7092 CharData storage;
7093
7094 CharData_Init(&storage);
7095 XML_SetStartElementHandler(g_parser, accumulate_attribute);
7096 XML_SetUserData(g_parser, &storage);
7097 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
7098 == XML_STATUS_ERROR)
7099 xml_failure(g_parser);
7100 CharData_CheckXMLChars(&storage, expected);
7101 }
7102 END_TEST
7103
START_TEST(test_ns_utf16_element_leafname)7104 START_TEST(test_ns_utf16_element_leafname) {
7105 const char text[] =
7106 /* <n:{KHO KHWAI} xmlns:n='URI'/>
7107 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
7108 */
7109 "\0<\0n\0:\x0e\x04\0 \0x\0m\0l\0n\0s\0:\0n\0=\0'\0U\0R\0I\0'\0/\0>";
7110 #ifdef XML_UNICODE
7111 const XML_Char *expected = XCS("URI \x0e04");
7112 #else
7113 const XML_Char *expected = XCS("URI \xe0\xb8\x84");
7114 #endif
7115 CharData storage;
7116
7117 CharData_Init(&storage);
7118 XML_SetStartElementHandler(g_parser, start_element_event_handler);
7119 XML_SetUserData(g_parser, &storage);
7120 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
7121 == XML_STATUS_ERROR)
7122 xml_failure(g_parser);
7123 CharData_CheckXMLChars(&storage, expected);
7124 }
7125 END_TEST
7126
START_TEST(test_ns_utf16_doctype)7127 START_TEST(test_ns_utf16_doctype) {
7128 const char text[] =
7129 /* <!DOCTYPE foo:{KHO KHWAI} [ <!ENTITY bar 'baz'> ]>\n
7130 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
7131 */
7132 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0f\0o\0o\0:\x0e\x04\0 "
7133 "\0[\0 \0<\0!\0E\0N\0T\0I\0T\0Y\0 \0b\0a\0r\0 \0'\0b\0a\0z\0'\0>\0 "
7134 "\0]\0>\0\n"
7135 /* <foo:{KHO KHWAI} xmlns:foo='URI'>&bar;</foo:{KHO KHWAI}> */
7136 "\0<\0f\0o\0o\0:\x0e\x04\0 "
7137 "\0x\0m\0l\0n\0s\0:\0f\0o\0o\0=\0'\0U\0R\0I\0'\0>"
7138 "\0&\0b\0a\0r\0;"
7139 "\0<\0/\0f\0o\0o\0:\x0e\x04\0>";
7140 #ifdef XML_UNICODE
7141 const XML_Char *expected = XCS("URI \x0e04");
7142 #else
7143 const XML_Char *expected = XCS("URI \xe0\xb8\x84");
7144 #endif
7145 CharData storage;
7146
7147 CharData_Init(&storage);
7148 XML_SetUserData(g_parser, &storage);
7149 XML_SetStartElementHandler(g_parser, start_element_event_handler);
7150 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
7151 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
7152 == XML_STATUS_ERROR)
7153 xml_failure(g_parser);
7154 CharData_CheckXMLChars(&storage, expected);
7155 }
7156 END_TEST
7157
START_TEST(test_ns_invalid_doctype)7158 START_TEST(test_ns_invalid_doctype) {
7159 const char *text = "<!DOCTYPE foo:!bad [ <!ENTITY bar 'baz' ]>\n"
7160 "<foo:!bad>&bar;</foo:!bad>";
7161
7162 expect_failure(text, XML_ERROR_INVALID_TOKEN,
7163 "Invalid character in document local name not faulted");
7164 }
7165 END_TEST
7166
START_TEST(test_ns_double_colon_doctype)7167 START_TEST(test_ns_double_colon_doctype) {
7168 const char *text = "<!DOCTYPE foo:a:doc [ <!ENTITY bar 'baz' ]>\n"
7169 "<foo:a:doc>&bar;</foo:a:doc>";
7170
7171 expect_failure(text, XML_ERROR_SYNTAX,
7172 "Double colon in document name not faulted");
7173 }
7174 END_TEST
7175
7176 /* Control variable; the number of times duff_allocator() will successfully
7177 * allocate */
7178 #define ALLOC_ALWAYS_SUCCEED (-1)
7179 #define REALLOC_ALWAYS_SUCCEED (-1)
7180
7181 static intptr_t allocation_count = ALLOC_ALWAYS_SUCCEED;
7182 static intptr_t reallocation_count = REALLOC_ALWAYS_SUCCEED;
7183
7184 /* Crocked allocator for allocation failure tests */
7185 static void *
duff_allocator(size_t size)7186 duff_allocator(size_t size) {
7187 if (allocation_count == 0)
7188 return NULL;
7189 if (allocation_count != ALLOC_ALWAYS_SUCCEED)
7190 allocation_count--;
7191 return malloc(size);
7192 }
7193
7194 /* Crocked reallocator for allocation failure tests */
7195 static void *
duff_reallocator(void * ptr,size_t size)7196 duff_reallocator(void *ptr, size_t size) {
7197 if (reallocation_count == 0)
7198 return NULL;
7199 if (reallocation_count != REALLOC_ALWAYS_SUCCEED)
7200 reallocation_count--;
7201 return realloc(ptr, size);
7202 }
7203
7204 /* Test that a failure to allocate the parser structure fails gracefully */
START_TEST(test_misc_alloc_create_parser)7205 START_TEST(test_misc_alloc_create_parser) {
7206 XML_Memory_Handling_Suite memsuite = {duff_allocator, realloc, free};
7207 unsigned int i;
7208 const unsigned int max_alloc_count = 10;
7209
7210 /* Something this simple shouldn't need more than 10 allocations */
7211 for (i = 0; i < max_alloc_count; i++) {
7212 allocation_count = i;
7213 g_parser = XML_ParserCreate_MM(NULL, &memsuite, NULL);
7214 if (g_parser != NULL)
7215 break;
7216 }
7217 if (i == 0)
7218 fail("Parser unexpectedly ignored failing allocator");
7219 else if (i == max_alloc_count)
7220 fail("Parser not created with max allocation count");
7221 }
7222 END_TEST
7223
7224 /* Test memory allocation failures for a parser with an encoding */
START_TEST(test_misc_alloc_create_parser_with_encoding)7225 START_TEST(test_misc_alloc_create_parser_with_encoding) {
7226 XML_Memory_Handling_Suite memsuite = {duff_allocator, realloc, free};
7227 unsigned int i;
7228 const unsigned int max_alloc_count = 10;
7229
7230 /* Try several levels of allocation */
7231 for (i = 0; i < max_alloc_count; i++) {
7232 allocation_count = i;
7233 g_parser = XML_ParserCreate_MM(XCS("us-ascii"), &memsuite, NULL);
7234 if (g_parser != NULL)
7235 break;
7236 }
7237 if (i == 0)
7238 fail("Parser ignored failing allocator");
7239 else if (i == max_alloc_count)
7240 fail("Parser not created with max allocation count");
7241 }
7242 END_TEST
7243
7244 /* Test that freeing a NULL parser doesn't cause an explosion.
7245 * (Not actually tested anywhere else)
7246 */
START_TEST(test_misc_null_parser)7247 START_TEST(test_misc_null_parser) {
7248 XML_ParserFree(NULL);
7249 }
7250 END_TEST
7251
7252 /* Test that XML_ErrorString rejects out-of-range codes */
START_TEST(test_misc_error_string)7253 START_TEST(test_misc_error_string) {
7254 if (XML_ErrorString((enum XML_Error) - 1) != NULL)
7255 fail("Negative error code not rejected");
7256 if (XML_ErrorString((enum XML_Error)100) != NULL)
7257 fail("Large error code not rejected");
7258 }
7259 END_TEST
7260
7261 /* Test the version information is consistent */
7262
7263 /* Since we are working in XML_LChars (potentially 16-bits), we
7264 * can't use the standard C library functions for character
7265 * manipulation and have to roll our own.
7266 */
7267 static int
parse_version(const XML_LChar * version_text,XML_Expat_Version * version_struct)7268 parse_version(const XML_LChar *version_text,
7269 XML_Expat_Version *version_struct) {
7270 if (! version_text)
7271 return XML_FALSE;
7272
7273 while (*version_text != 0x00) {
7274 if (*version_text >= ASCII_0 && *version_text <= ASCII_9)
7275 break;
7276 version_text++;
7277 }
7278 if (*version_text == 0x00)
7279 return XML_FALSE;
7280
7281 /* version_struct->major = strtoul(version_text, 10, &version_text) */
7282 version_struct->major = 0;
7283 while (*version_text >= ASCII_0 && *version_text <= ASCII_9) {
7284 version_struct->major
7285 = 10 * version_struct->major + (*version_text++ - ASCII_0);
7286 }
7287 if (*version_text++ != ASCII_PERIOD)
7288 return XML_FALSE;
7289
7290 /* Now for the minor version number */
7291 version_struct->minor = 0;
7292 while (*version_text >= ASCII_0 && *version_text <= ASCII_9) {
7293 version_struct->minor
7294 = 10 * version_struct->minor + (*version_text++ - ASCII_0);
7295 }
7296 if (*version_text++ != ASCII_PERIOD)
7297 return XML_FALSE;
7298
7299 /* Finally the micro version number */
7300 version_struct->micro = 0;
7301 while (*version_text >= ASCII_0 && *version_text <= ASCII_9) {
7302 version_struct->micro
7303 = 10 * version_struct->micro + (*version_text++ - ASCII_0);
7304 }
7305 if (*version_text != 0x00)
7306 return XML_FALSE;
7307 return XML_TRUE;
7308 }
7309
7310 static int
versions_equal(const XML_Expat_Version * first,const XML_Expat_Version * second)7311 versions_equal(const XML_Expat_Version *first,
7312 const XML_Expat_Version *second) {
7313 return (first->major == second->major && first->minor == second->minor
7314 && first->micro == second->micro);
7315 }
7316
START_TEST(test_misc_version)7317 START_TEST(test_misc_version) {
7318 XML_Expat_Version read_version = XML_ExpatVersionInfo();
7319 /* Silence compiler warning with the following assignment */
7320 XML_Expat_Version parsed_version = {0, 0, 0};
7321 const XML_LChar *version_text = XML_ExpatVersion();
7322
7323 if (version_text == NULL)
7324 fail("Could not obtain version text");
7325 assert(version_text != NULL);
7326 if (! parse_version(version_text, &parsed_version))
7327 fail("Unable to parse version text");
7328 if (! versions_equal(&read_version, &parsed_version))
7329 fail("Version mismatch");
7330
7331 #if ! defined(XML_UNICODE) || defined(XML_UNICODE_WCHAR_T)
7332 if (xcstrcmp(version_text, XCS("expat_2.2.9"))) /* needs bump on releases */
7333 fail("XML_*_VERSION in expat.h out of sync?\n");
7334 #else
7335 /* If we have XML_UNICODE defined but not XML_UNICODE_WCHAR_T
7336 * then XML_LChar is defined as char, for some reason.
7337 */
7338 if (strcmp(version_text, "expat_2.2.5")) /* needs bump on releases */
7339 fail("XML_*_VERSION in expat.h out of sync?\n");
7340 #endif /* ! defined(XML_UNICODE) || defined(XML_UNICODE_WCHAR_T) */
7341 }
7342 END_TEST
7343
7344 /* Test feature information */
START_TEST(test_misc_features)7345 START_TEST(test_misc_features) {
7346 const XML_Feature *features = XML_GetFeatureList();
7347
7348 /* Prevent problems with double-freeing parsers */
7349 g_parser = NULL;
7350 if (features == NULL) {
7351 fail("Failed to get feature information");
7352 } else {
7353 /* Loop through the features checking what we can */
7354 while (features->feature != XML_FEATURE_END) {
7355 switch (features->feature) {
7356 case XML_FEATURE_SIZEOF_XML_CHAR:
7357 if (features->value != sizeof(XML_Char))
7358 fail("Incorrect size of XML_Char");
7359 break;
7360 case XML_FEATURE_SIZEOF_XML_LCHAR:
7361 if (features->value != sizeof(XML_LChar))
7362 fail("Incorrect size of XML_LChar");
7363 break;
7364 default:
7365 break;
7366 }
7367 features++;
7368 }
7369 }
7370 }
7371 END_TEST
7372
7373 /* Regression test for GitHub Issue #17: memory leak parsing attribute
7374 * values with mixed bound and unbound namespaces.
7375 */
START_TEST(test_misc_attribute_leak)7376 START_TEST(test_misc_attribute_leak) {
7377 const char *text = "<D xmlns:L=\"D\" l:a='' L:a=''/>";
7378 XML_Memory_Handling_Suite memsuite
7379 = {tracking_malloc, tracking_realloc, tracking_free};
7380
7381 g_parser = XML_ParserCreate_MM(XCS("UTF-8"), &memsuite, XCS("\n"));
7382 expect_failure(text, XML_ERROR_UNBOUND_PREFIX, "Unbound prefixes not found");
7383 XML_ParserFree(g_parser);
7384 /* Prevent the teardown trying to double free */
7385 g_parser = NULL;
7386
7387 if (! tracking_report())
7388 fail("Memory leak found");
7389 }
7390 END_TEST
7391
7392 /* Test parser created for UTF-16LE is successful */
START_TEST(test_misc_utf16le)7393 START_TEST(test_misc_utf16le) {
7394 const char text[] =
7395 /* <?xml version='1.0'?><q>Hi</q> */
7396 "<\0?\0x\0m\0l\0 \0"
7397 "v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0?\0>\0"
7398 "<\0q\0>\0H\0i\0<\0/\0q\0>\0";
7399 const XML_Char *expected = XCS("Hi");
7400 CharData storage;
7401
7402 g_parser = XML_ParserCreate(XCS("UTF-16LE"));
7403 if (g_parser == NULL)
7404 fail("Parser not created");
7405
7406 CharData_Init(&storage);
7407 XML_SetUserData(g_parser, &storage);
7408 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
7409 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
7410 == XML_STATUS_ERROR)
7411 xml_failure(g_parser);
7412 CharData_CheckXMLChars(&storage, expected);
7413 }
7414 END_TEST
7415
7416 typedef struct {
7417 XML_Parser parser;
7418 int deep;
7419 } DataIssue240;
7420
7421 static void
start_element_issue_240(void * userData,const XML_Char * name,const XML_Char ** atts)7422 start_element_issue_240(void *userData, const XML_Char *name,
7423 const XML_Char **atts) {
7424 DataIssue240 *mydata = (DataIssue240 *)userData;
7425 UNUSED_P(name);
7426 UNUSED_P(atts);
7427 mydata->deep++;
7428 }
7429
7430 static void
end_element_issue_240(void * userData,const XML_Char * name)7431 end_element_issue_240(void *userData, const XML_Char *name) {
7432 DataIssue240 *mydata = (DataIssue240 *)userData;
7433
7434 UNUSED_P(name);
7435 mydata->deep--;
7436 if (mydata->deep == 0) {
7437 XML_StopParser(mydata->parser, 0);
7438 }
7439 }
7440
START_TEST(test_misc_stop_during_end_handler_issue_240_1)7441 START_TEST(test_misc_stop_during_end_handler_issue_240_1) {
7442 XML_Parser parser;
7443 DataIssue240 *mydata;
7444 enum XML_Status result;
7445 const char *const doc1 = "<doc><e1/><e><foo/></e></doc>";
7446
7447 parser = XML_ParserCreate(NULL);
7448 XML_SetElementHandler(parser, start_element_issue_240, end_element_issue_240);
7449 mydata = (DataIssue240 *)malloc(sizeof(DataIssue240));
7450 mydata->parser = parser;
7451 mydata->deep = 0;
7452 XML_SetUserData(parser, mydata);
7453
7454 result = XML_Parse(parser, doc1, (int)strlen(doc1), 1);
7455 XML_ParserFree(parser);
7456 free(mydata);
7457 if (result != XML_STATUS_ERROR)
7458 fail("Stopping the parser did not work as expected");
7459 }
7460 END_TEST
7461
START_TEST(test_misc_stop_during_end_handler_issue_240_2)7462 START_TEST(test_misc_stop_during_end_handler_issue_240_2) {
7463 XML_Parser parser;
7464 DataIssue240 *mydata;
7465 enum XML_Status result;
7466 const char *const doc2 = "<doc><elem/></doc>";
7467
7468 parser = XML_ParserCreate(NULL);
7469 XML_SetElementHandler(parser, start_element_issue_240, end_element_issue_240);
7470 mydata = (DataIssue240 *)malloc(sizeof(DataIssue240));
7471 mydata->parser = parser;
7472 mydata->deep = 0;
7473 XML_SetUserData(parser, mydata);
7474
7475 result = XML_Parse(parser, doc2, (int)strlen(doc2), 1);
7476 XML_ParserFree(parser);
7477 free(mydata);
7478 if (result != XML_STATUS_ERROR)
7479 fail("Stopping the parser did not work as expected");
7480 }
7481 END_TEST
7482
7483 #ifdef XML_DTD
START_TEST(test_misc_deny_internal_entity_closing_doctype_issue_317)7484 START_TEST(test_misc_deny_internal_entity_closing_doctype_issue_317) {
7485 const char *const inputOne = "<!DOCTYPE d [\n"
7486 "<!ENTITY % e ']><d/>'>\n"
7487 "\n"
7488 "%e;";
7489 const char *const inputTwo = "<!DOCTYPE d [\n"
7490 "<!ENTITY % e1 ']><d/>'><!ENTITY % e2 '&e1;'>\n"
7491 "\n"
7492 "%e2;";
7493 const char *const inputThree = "<!DOCTYPE d [\n"
7494 "<!ENTITY % e ']><d'>\n"
7495 "\n"
7496 "%e;";
7497 const char *const inputIssue317 = "<!DOCTYPE doc [\n"
7498 "<!ENTITY % foo ']>\n"
7499 "<doc>Hell<oc (#PCDATA)*>'>\n"
7500 "%foo;\n"
7501 "]>\n"
7502 "<doc>Hello, world</dVc>";
7503
7504 const char *const inputs[] = {inputOne, inputTwo, inputThree, inputIssue317};
7505 size_t inputIndex = 0;
7506
7507 for (; inputIndex < sizeof(inputs) / sizeof(inputs[0]); inputIndex++) {
7508 XML_Parser parser;
7509 enum XML_Status parseResult;
7510 int setParamEntityResult;
7511 XML_Size lineNumber;
7512 XML_Size columnNumber;
7513 const char *const input = inputs[inputIndex];
7514
7515 parser = XML_ParserCreate(NULL);
7516 setParamEntityResult
7517 = XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
7518 if (setParamEntityResult != 1)
7519 fail("Failed to set XML_PARAM_ENTITY_PARSING_ALWAYS.");
7520
7521 parseResult = XML_Parse(parser, input, (int)strlen(input), 0);
7522 if (parseResult != XML_STATUS_ERROR) {
7523 parseResult = XML_Parse(parser, "", 0, 1);
7524 if (parseResult != XML_STATUS_ERROR) {
7525 fail("Parsing was expected to fail but succeeded.");
7526 }
7527 }
7528
7529 if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN)
7530 fail("Error code does not match XML_ERROR_INVALID_TOKEN");
7531
7532 lineNumber = XML_GetCurrentLineNumber(parser);
7533 if (lineNumber != 4)
7534 fail("XML_GetCurrentLineNumber does not work as expected.");
7535
7536 columnNumber = XML_GetCurrentColumnNumber(parser);
7537 if (columnNumber != 0)
7538 fail("XML_GetCurrentColumnNumber does not work as expected.");
7539
7540 XML_ParserFree(parser);
7541 }
7542 }
7543 END_TEST
7544 #endif
7545
7546 static void
alloc_setup(void)7547 alloc_setup(void) {
7548 XML_Memory_Handling_Suite memsuite = {duff_allocator, duff_reallocator, free};
7549
7550 /* Ensure the parser creation will go through */
7551 allocation_count = ALLOC_ALWAYS_SUCCEED;
7552 reallocation_count = REALLOC_ALWAYS_SUCCEED;
7553 g_parser = XML_ParserCreate_MM(NULL, &memsuite, NULL);
7554 if (g_parser == NULL)
7555 fail("Parser not created");
7556 }
7557
7558 static void
alloc_teardown(void)7559 alloc_teardown(void) {
7560 basic_teardown();
7561 }
7562
7563 /* Test the effects of allocation failures on xml declaration processing */
START_TEST(test_alloc_parse_xdecl)7564 START_TEST(test_alloc_parse_xdecl) {
7565 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
7566 "<doc>Hello, world</doc>";
7567 int i;
7568 const int max_alloc_count = 15;
7569
7570 for (i = 0; i < max_alloc_count; i++) {
7571 allocation_count = i;
7572 XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler);
7573 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7574 != XML_STATUS_ERROR)
7575 break;
7576 /* Resetting the parser is insufficient, because some memory
7577 * allocations are cached within the parser. Instead we use
7578 * the teardown and setup routines to ensure that we have the
7579 * right sort of parser back in our hands.
7580 */
7581 alloc_teardown();
7582 alloc_setup();
7583 }
7584 if (i == 0)
7585 fail("Parse succeeded despite failing allocator");
7586 if (i == max_alloc_count)
7587 fail("Parse failed with max allocations");
7588 }
7589 END_TEST
7590
7591 /* As above, but with an encoding big enough to cause storing the
7592 * version information to expand the string pool being used.
7593 */
7594 static int XMLCALL
long_encoding_handler(void * userData,const XML_Char * encoding,XML_Encoding * info)7595 long_encoding_handler(void *userData, const XML_Char *encoding,
7596 XML_Encoding *info) {
7597 int i;
7598
7599 UNUSED_P(userData);
7600 UNUSED_P(encoding);
7601 for (i = 0; i < 256; i++)
7602 info->map[i] = i;
7603 info->data = NULL;
7604 info->convert = NULL;
7605 info->release = NULL;
7606 return XML_STATUS_OK;
7607 }
7608
START_TEST(test_alloc_parse_xdecl_2)7609 START_TEST(test_alloc_parse_xdecl_2) {
7610 const char *text
7611 = "<?xml version='1.0' encoding='"
7612 /* Each line is 64 characters */
7613 "ThisIsAStupidlyLongEncodingNameIntendedToTriggerPoolGrowth123456"
7614 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7615 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7616 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7617 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7618 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7619 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7620 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7621 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7622 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7623 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7624 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7625 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7626 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7627 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7628 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN"
7629 "'?>"
7630 "<doc>Hello, world</doc>";
7631 int i;
7632 const int max_alloc_count = 20;
7633
7634 for (i = 0; i < max_alloc_count; i++) {
7635 allocation_count = i;
7636 XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler);
7637 XML_SetUnknownEncodingHandler(g_parser, long_encoding_handler, NULL);
7638 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7639 != XML_STATUS_ERROR)
7640 break;
7641 /* See comment in test_alloc_parse_xdecl() */
7642 alloc_teardown();
7643 alloc_setup();
7644 }
7645 if (i == 0)
7646 fail("Parse succeeded despite failing allocator");
7647 if (i == max_alloc_count)
7648 fail("Parse failed with max allocations");
7649 }
7650 END_TEST
7651
7652 /* Test the effects of allocation failures on a straightforward parse */
START_TEST(test_alloc_parse_pi)7653 START_TEST(test_alloc_parse_pi) {
7654 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
7655 "<?pi unknown?>\n"
7656 "<doc>"
7657 "Hello, world"
7658 "</doc>";
7659 int i;
7660 const int max_alloc_count = 15;
7661
7662 for (i = 0; i < max_alloc_count; i++) {
7663 allocation_count = i;
7664 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
7665 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7666 != XML_STATUS_ERROR)
7667 break;
7668 /* See comment in test_alloc_parse_xdecl() */
7669 alloc_teardown();
7670 alloc_setup();
7671 }
7672 if (i == 0)
7673 fail("Parse succeeded despite failing allocator");
7674 if (i == max_alloc_count)
7675 fail("Parse failed with max allocations");
7676 }
7677 END_TEST
7678
START_TEST(test_alloc_parse_pi_2)7679 START_TEST(test_alloc_parse_pi_2) {
7680 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
7681 "<doc>"
7682 "Hello, world"
7683 "<?pi unknown?>\n"
7684 "</doc>";
7685 int i;
7686 const int max_alloc_count = 15;
7687
7688 for (i = 0; i < max_alloc_count; i++) {
7689 allocation_count = i;
7690 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
7691 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7692 != XML_STATUS_ERROR)
7693 break;
7694 /* See comment in test_alloc_parse_xdecl() */
7695 alloc_teardown();
7696 alloc_setup();
7697 }
7698 if (i == 0)
7699 fail("Parse succeeded despite failing allocator");
7700 if (i == max_alloc_count)
7701 fail("Parse failed with max allocations");
7702 }
7703 END_TEST
7704
START_TEST(test_alloc_parse_pi_3)7705 START_TEST(test_alloc_parse_pi_3) {
7706 const char *text
7707 = "<?"
7708 /* 64 characters per line */
7709 "This processing instruction should be long enough to ensure that"
7710 "it triggers the growth of an internal string pool when the "
7711 "allocator fails at a cruicial moment FGHIJKLMNOPABCDEFGHIJKLMNOP"
7712 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7713 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7714 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7715 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7716 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7717 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7718 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7719 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7720 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7721 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7722 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7723 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7724 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7725 "Q?><doc/>";
7726 int i;
7727 const int max_alloc_count = 20;
7728
7729 for (i = 0; i < max_alloc_count; i++) {
7730 allocation_count = i;
7731 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
7732 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7733 != XML_STATUS_ERROR)
7734 break;
7735 /* See comment in test_alloc_parse_xdecl() */
7736 alloc_teardown();
7737 alloc_setup();
7738 }
7739 if (i == 0)
7740 fail("Parse succeeded despite failing allocator");
7741 if (i == max_alloc_count)
7742 fail("Parse failed with max allocations");
7743 }
7744 END_TEST
7745
START_TEST(test_alloc_parse_comment)7746 START_TEST(test_alloc_parse_comment) {
7747 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
7748 "<!-- Test parsing this comment -->"
7749 "<doc>Hi</doc>";
7750 int i;
7751 const int max_alloc_count = 15;
7752
7753 for (i = 0; i < max_alloc_count; i++) {
7754 allocation_count = i;
7755 XML_SetCommentHandler(g_parser, dummy_comment_handler);
7756 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7757 != XML_STATUS_ERROR)
7758 break;
7759 /* See comment in test_alloc_parse_xdecl() */
7760 alloc_teardown();
7761 alloc_setup();
7762 }
7763 if (i == 0)
7764 fail("Parse succeeded despite failing allocator");
7765 if (i == max_alloc_count)
7766 fail("Parse failed with max allocations");
7767 }
7768 END_TEST
7769
START_TEST(test_alloc_parse_comment_2)7770 START_TEST(test_alloc_parse_comment_2) {
7771 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
7772 "<doc>"
7773 "Hello, world"
7774 "<!-- Parse this comment too -->"
7775 "</doc>";
7776 int i;
7777 const int max_alloc_count = 15;
7778
7779 for (i = 0; i < max_alloc_count; i++) {
7780 allocation_count = i;
7781 XML_SetCommentHandler(g_parser, dummy_comment_handler);
7782 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7783 != XML_STATUS_ERROR)
7784 break;
7785 /* See comment in test_alloc_parse_xdecl() */
7786 alloc_teardown();
7787 alloc_setup();
7788 }
7789 if (i == 0)
7790 fail("Parse succeeded despite failing allocator");
7791 if (i == max_alloc_count)
7792 fail("Parse failed with max allocations");
7793 }
7794 END_TEST
7795
7796 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)7797 external_entity_duff_loader(XML_Parser parser, const XML_Char *context,
7798 const XML_Char *base, const XML_Char *systemId,
7799 const XML_Char *publicId) {
7800 XML_Parser new_parser;
7801 unsigned int i;
7802 const unsigned int max_alloc_count = 10;
7803
7804 UNUSED_P(base);
7805 UNUSED_P(systemId);
7806 UNUSED_P(publicId);
7807 /* Try a few different allocation levels */
7808 for (i = 0; i < max_alloc_count; i++) {
7809 allocation_count = i;
7810 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
7811 if (new_parser != NULL) {
7812 XML_ParserFree(new_parser);
7813 break;
7814 }
7815 }
7816 if (i == 0)
7817 fail("External parser creation ignored failing allocator");
7818 else if (i == max_alloc_count)
7819 fail("Extern parser not created with max allocation count");
7820
7821 /* Make sure other random allocation doesn't now fail */
7822 allocation_count = ALLOC_ALWAYS_SUCCEED;
7823
7824 /* Make sure the failure code path is executed too */
7825 return XML_STATUS_ERROR;
7826 }
7827
7828 /* Test that external parser creation running out of memory is
7829 * correctly reported. Based on the external entity test cases.
7830 */
START_TEST(test_alloc_create_external_parser)7831 START_TEST(test_alloc_create_external_parser) {
7832 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
7833 "<!DOCTYPE doc SYSTEM 'foo'>\n"
7834 "<doc>&entity;</doc>";
7835 char foo_text[] = "<!ELEMENT doc (#PCDATA)*>";
7836
7837 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
7838 XML_SetUserData(g_parser, foo_text);
7839 XML_SetExternalEntityRefHandler(g_parser, external_entity_duff_loader);
7840 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7841 != XML_STATUS_ERROR) {
7842 fail("External parser allocator returned success incorrectly");
7843 }
7844 }
7845 END_TEST
7846
7847 /* More external parser memory allocation testing */
START_TEST(test_alloc_run_external_parser)7848 START_TEST(test_alloc_run_external_parser) {
7849 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
7850 "<!DOCTYPE doc SYSTEM 'foo'>\n"
7851 "<doc>&entity;</doc>";
7852 char foo_text[] = "<!ELEMENT doc (#PCDATA)*>";
7853 unsigned int i;
7854 const unsigned int max_alloc_count = 15;
7855
7856 for (i = 0; i < max_alloc_count; i++) {
7857 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
7858 XML_SetUserData(g_parser, foo_text);
7859 XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader);
7860 allocation_count = i;
7861 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7862 != XML_STATUS_ERROR)
7863 break;
7864 /* See comment in test_alloc_parse_xdecl() */
7865 alloc_teardown();
7866 alloc_setup();
7867 }
7868 if (i == 0)
7869 fail("Parsing ignored failing allocator");
7870 else if (i == max_alloc_count)
7871 fail("Parsing failed with allocation count 10");
7872 }
7873 END_TEST
7874
7875 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)7876 external_entity_dbl_handler(XML_Parser parser, const XML_Char *context,
7877 const XML_Char *base, const XML_Char *systemId,
7878 const XML_Char *publicId) {
7879 intptr_t callno = (intptr_t)XML_GetUserData(parser);
7880 const char *text;
7881 XML_Parser new_parser;
7882 int i;
7883 const int max_alloc_count = 20;
7884
7885 UNUSED_P(base);
7886 UNUSED_P(systemId);
7887 UNUSED_P(publicId);
7888 if (callno == 0) {
7889 /* First time through, check how many calls to malloc occur */
7890 text = ("<!ELEMENT doc (e+)>\n"
7891 "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
7892 "<!ELEMENT e EMPTY>\n");
7893 allocation_count = 10000;
7894 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
7895 if (new_parser == NULL) {
7896 fail("Unable to allocate first external parser");
7897 return XML_STATUS_ERROR;
7898 }
7899 /* Stash the number of calls in the user data */
7900 XML_SetUserData(parser, (void *)(intptr_t)(10000 - allocation_count));
7901 } else {
7902 text = ("<?xml version='1.0' encoding='us-ascii'?>"
7903 "<e/>");
7904 /* Try at varying levels to exercise more code paths */
7905 for (i = 0; i < max_alloc_count; i++) {
7906 allocation_count = callno + i;
7907 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
7908 if (new_parser != NULL)
7909 break;
7910 }
7911 if (i == 0) {
7912 fail("Second external parser unexpectedly created");
7913 XML_ParserFree(new_parser);
7914 return XML_STATUS_ERROR;
7915 } else if (i == max_alloc_count) {
7916 fail("Second external parser not created");
7917 return XML_STATUS_ERROR;
7918 }
7919 }
7920
7921 allocation_count = ALLOC_ALWAYS_SUCCEED;
7922 if (_XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE)
7923 == XML_STATUS_ERROR) {
7924 xml_failure(new_parser);
7925 return XML_STATUS_ERROR;
7926 }
7927 XML_ParserFree(new_parser);
7928 return XML_STATUS_OK;
7929 }
7930
7931 /* Test that running out of memory in dtdCopy is correctly reported.
7932 * Based on test_default_ns_from_ext_subset_and_ext_ge()
7933 */
START_TEST(test_alloc_dtd_copy_default_atts)7934 START_TEST(test_alloc_dtd_copy_default_atts) {
7935 const char *text = "<?xml version='1.0'?>\n"
7936 "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n"
7937 " <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n"
7938 "]>\n"
7939 "<doc xmlns='http://example.org/ns1'>\n"
7940 "&en;\n"
7941 "</doc>";
7942
7943 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
7944 XML_SetExternalEntityRefHandler(g_parser, external_entity_dbl_handler);
7945 XML_SetUserData(g_parser, NULL);
7946 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7947 == XML_STATUS_ERROR)
7948 xml_failure(g_parser);
7949 }
7950 END_TEST
7951
7952 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)7953 external_entity_dbl_handler_2(XML_Parser parser, const XML_Char *context,
7954 const XML_Char *base, const XML_Char *systemId,
7955 const XML_Char *publicId) {
7956 intptr_t callno = (intptr_t)XML_GetUserData(parser);
7957 const char *text;
7958 XML_Parser new_parser;
7959 enum XML_Status rv;
7960
7961 UNUSED_P(base);
7962 UNUSED_P(systemId);
7963 UNUSED_P(publicId);
7964 if (callno == 0) {
7965 /* Try different allocation levels for whole exercise */
7966 text = ("<!ELEMENT doc (e+)>\n"
7967 "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
7968 "<!ELEMENT e EMPTY>\n");
7969 XML_SetUserData(parser, (void *)(intptr_t)1);
7970 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
7971 if (new_parser == NULL)
7972 return XML_STATUS_ERROR;
7973 rv = _XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE);
7974 } else {
7975 /* Just run through once */
7976 text = ("<?xml version='1.0' encoding='us-ascii'?>"
7977 "<e/>");
7978 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
7979 if (new_parser == NULL)
7980 return XML_STATUS_ERROR;
7981 rv = _XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE);
7982 }
7983 XML_ParserFree(new_parser);
7984 if (rv == XML_STATUS_ERROR)
7985 return XML_STATUS_ERROR;
7986 return XML_STATUS_OK;
7987 }
7988
7989 /* Test more external entity allocation failure paths */
START_TEST(test_alloc_external_entity)7990 START_TEST(test_alloc_external_entity) {
7991 const char *text = "<?xml version='1.0'?>\n"
7992 "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n"
7993 " <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n"
7994 "]>\n"
7995 "<doc xmlns='http://example.org/ns1'>\n"
7996 "&en;\n"
7997 "</doc>";
7998 int i;
7999 const int alloc_test_max_repeats = 50;
8000
8001 for (i = 0; i < alloc_test_max_repeats; i++) {
8002 allocation_count = -1;
8003 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8004 XML_SetExternalEntityRefHandler(g_parser, external_entity_dbl_handler_2);
8005 XML_SetUserData(g_parser, NULL);
8006 allocation_count = i;
8007 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8008 == XML_STATUS_OK)
8009 break;
8010 /* See comment in test_alloc_parse_xdecl() */
8011 alloc_teardown();
8012 alloc_setup();
8013 }
8014 allocation_count = -1;
8015 if (i == 0)
8016 fail("External entity parsed despite duff allocator");
8017 if (i == alloc_test_max_repeats)
8018 fail("External entity not parsed at max allocation count");
8019 }
8020 END_TEST
8021
8022 /* Test more allocation failure paths */
8023 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)8024 external_entity_alloc_set_encoding(XML_Parser parser, const XML_Char *context,
8025 const XML_Char *base,
8026 const XML_Char *systemId,
8027 const XML_Char *publicId) {
8028 /* As for external_entity_loader() */
8029 const char *text = "<?xml encoding='iso-8859-3'?>"
8030 "\xC3\xA9";
8031 XML_Parser ext_parser;
8032 enum XML_Status status;
8033
8034 UNUSED_P(base);
8035 UNUSED_P(systemId);
8036 UNUSED_P(publicId);
8037 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8038 if (ext_parser == NULL)
8039 return XML_STATUS_ERROR;
8040 if (! XML_SetEncoding(ext_parser, XCS("utf-8"))) {
8041 XML_ParserFree(ext_parser);
8042 return XML_STATUS_ERROR;
8043 }
8044 status
8045 = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
8046 XML_ParserFree(ext_parser);
8047 if (status == XML_STATUS_ERROR)
8048 return XML_STATUS_ERROR;
8049 return XML_STATUS_OK;
8050 }
8051
START_TEST(test_alloc_ext_entity_set_encoding)8052 START_TEST(test_alloc_ext_entity_set_encoding) {
8053 const char *text = "<!DOCTYPE doc [\n"
8054 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
8055 "]>\n"
8056 "<doc>&en;</doc>";
8057 int i;
8058 const int max_allocation_count = 30;
8059
8060 for (i = 0; i < max_allocation_count; i++) {
8061 XML_SetExternalEntityRefHandler(g_parser,
8062 external_entity_alloc_set_encoding);
8063 allocation_count = i;
8064 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8065 == XML_STATUS_OK)
8066 break;
8067 allocation_count = -1;
8068 /* See comment in test_alloc_parse_xdecl() */
8069 alloc_teardown();
8070 alloc_setup();
8071 }
8072 if (i == 0)
8073 fail("Encoding check succeeded despite failing allocator");
8074 if (i == max_allocation_count)
8075 fail("Encoding failed at max allocation count");
8076 }
8077 END_TEST
8078
8079 static int XMLCALL
unknown_released_encoding_handler(void * data,const XML_Char * encoding,XML_Encoding * info)8080 unknown_released_encoding_handler(void *data, const XML_Char *encoding,
8081 XML_Encoding *info) {
8082 UNUSED_P(data);
8083 if (! xcstrcmp(encoding, XCS("unsupported-encoding"))) {
8084 int i;
8085
8086 for (i = 0; i < 256; i++)
8087 info->map[i] = i;
8088 info->data = NULL;
8089 info->convert = NULL;
8090 info->release = dummy_release;
8091 return XML_STATUS_OK;
8092 }
8093 return XML_STATUS_ERROR;
8094 }
8095
8096 /* Test the effects of allocation failure in internal entities.
8097 * Based on test_unknown_encoding_internal_entity
8098 */
START_TEST(test_alloc_internal_entity)8099 START_TEST(test_alloc_internal_entity) {
8100 const char *text = "<?xml version='1.0' encoding='unsupported-encoding'?>\n"
8101 "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n"
8102 "<test a='&foo;'/>";
8103 unsigned int i;
8104 const unsigned int max_alloc_count = 20;
8105
8106 for (i = 0; i < max_alloc_count; i++) {
8107 allocation_count = i;
8108 XML_SetUnknownEncodingHandler(g_parser, unknown_released_encoding_handler,
8109 NULL);
8110 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8111 != XML_STATUS_ERROR)
8112 break;
8113 /* See comment in test_alloc_parse_xdecl() */
8114 alloc_teardown();
8115 alloc_setup();
8116 }
8117 if (i == 0)
8118 fail("Internal entity worked despite failing allocations");
8119 else if (i == max_alloc_count)
8120 fail("Internal entity failed at max allocation count");
8121 }
8122 END_TEST
8123
8124 /* Test the robustness against allocation failure of element handling
8125 * Based on test_dtd_default_handling().
8126 */
START_TEST(test_alloc_dtd_default_handling)8127 START_TEST(test_alloc_dtd_default_handling) {
8128 const char *text = "<!DOCTYPE doc [\n"
8129 "<!ENTITY e SYSTEM 'http://example.org/e'>\n"
8130 "<!NOTATION n SYSTEM 'http://example.org/n'>\n"
8131 "<!ENTITY e1 SYSTEM 'http://example.org/e' NDATA n>\n"
8132 "<!ELEMENT doc (#PCDATA)>\n"
8133 "<!ATTLIST doc a CDATA #IMPLIED>\n"
8134 "<?pi in dtd?>\n"
8135 "<!--comment in dtd-->\n"
8136 "]>\n"
8137 "<doc><![CDATA[text in doc]]></doc>";
8138 const XML_Char *expected = XCS("\n\n\n\n\n\n\n\n\n<doc>text in doc</doc>");
8139 CharData storage;
8140 int i;
8141 const int max_alloc_count = 25;
8142
8143 for (i = 0; i < max_alloc_count; i++) {
8144 allocation_count = i;
8145 dummy_handler_flags = 0;
8146 XML_SetDefaultHandler(g_parser, accumulate_characters);
8147 XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_handler,
8148 dummy_end_doctype_handler);
8149 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
8150 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
8151 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
8152 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
8153 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
8154 XML_SetCommentHandler(g_parser, dummy_comment_handler);
8155 XML_SetCdataSectionHandler(g_parser, dummy_start_cdata_handler,
8156 dummy_end_cdata_handler);
8157 XML_SetUnparsedEntityDeclHandler(g_parser,
8158 dummy_unparsed_entity_decl_handler);
8159 CharData_Init(&storage);
8160 XML_SetUserData(g_parser, &storage);
8161 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
8162 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8163 != XML_STATUS_ERROR)
8164 break;
8165 /* See comment in test_alloc_parse_xdecl() */
8166 alloc_teardown();
8167 alloc_setup();
8168 }
8169 if (i == 0)
8170 fail("Default DTD parsed despite allocation failures");
8171 if (i == max_alloc_count)
8172 fail("Default DTD not parsed with maximum alloc count");
8173 CharData_CheckXMLChars(&storage, expected);
8174 if (dummy_handler_flags
8175 != (DUMMY_START_DOCTYPE_HANDLER_FLAG | DUMMY_END_DOCTYPE_HANDLER_FLAG
8176 | DUMMY_ENTITY_DECL_HANDLER_FLAG | DUMMY_NOTATION_DECL_HANDLER_FLAG
8177 | DUMMY_ELEMENT_DECL_HANDLER_FLAG | DUMMY_ATTLIST_DECL_HANDLER_FLAG
8178 | DUMMY_COMMENT_HANDLER_FLAG | DUMMY_PI_HANDLER_FLAG
8179 | DUMMY_START_CDATA_HANDLER_FLAG | DUMMY_END_CDATA_HANDLER_FLAG
8180 | DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG))
8181 fail("Not all handlers were called");
8182 }
8183 END_TEST
8184
8185 /* Test robustness of XML_SetEncoding() with a failing allocator */
START_TEST(test_alloc_explicit_encoding)8186 START_TEST(test_alloc_explicit_encoding) {
8187 int i;
8188 const int max_alloc_count = 5;
8189
8190 for (i = 0; i < max_alloc_count; i++) {
8191 allocation_count = i;
8192 if (XML_SetEncoding(g_parser, XCS("us-ascii")) == XML_STATUS_OK)
8193 break;
8194 }
8195 if (i == 0)
8196 fail("Encoding set despite failing allocator");
8197 else if (i == max_alloc_count)
8198 fail("Encoding not set at max allocation count");
8199 }
8200 END_TEST
8201
8202 /* Test robustness of XML_SetBase against a failing allocator */
START_TEST(test_alloc_set_base)8203 START_TEST(test_alloc_set_base) {
8204 const XML_Char *new_base = XCS("/local/file/name.xml");
8205 int i;
8206 const int max_alloc_count = 5;
8207
8208 for (i = 0; i < max_alloc_count; i++) {
8209 allocation_count = i;
8210 if (XML_SetBase(g_parser, new_base) == XML_STATUS_OK)
8211 break;
8212 }
8213 if (i == 0)
8214 fail("Base set despite failing allocator");
8215 else if (i == max_alloc_count)
8216 fail("Base not set with max allocation count");
8217 }
8218 END_TEST
8219
8220 /* Test buffer extension in the face of a duff reallocator */
START_TEST(test_alloc_realloc_buffer)8221 START_TEST(test_alloc_realloc_buffer) {
8222 const char *text = get_buffer_test_text;
8223 void *buffer;
8224 int i;
8225 const int max_realloc_count = 10;
8226
8227 /* Get a smallish buffer */
8228 for (i = 0; i < max_realloc_count; i++) {
8229 reallocation_count = i;
8230 buffer = XML_GetBuffer(g_parser, 1536);
8231 if (buffer == NULL)
8232 fail("1.5K buffer reallocation failed");
8233 assert(buffer != NULL);
8234 memcpy(buffer, text, strlen(text));
8235 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE)
8236 == XML_STATUS_OK)
8237 break;
8238 /* See comment in test_alloc_parse_xdecl() */
8239 alloc_teardown();
8240 alloc_setup();
8241 }
8242 reallocation_count = -1;
8243 if (i == 0)
8244 fail("Parse succeeded with no reallocation");
8245 else if (i == max_realloc_count)
8246 fail("Parse failed with max reallocation count");
8247 }
8248 END_TEST
8249
8250 /* Same test for external entity parsers */
8251 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)8252 external_entity_reallocator(XML_Parser parser, const XML_Char *context,
8253 const XML_Char *base, const XML_Char *systemId,
8254 const XML_Char *publicId) {
8255 const char *text = get_buffer_test_text;
8256 XML_Parser ext_parser;
8257 void *buffer;
8258 enum XML_Status status;
8259
8260 UNUSED_P(base);
8261 UNUSED_P(systemId);
8262 UNUSED_P(publicId);
8263 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8264 if (ext_parser == NULL)
8265 fail("Could not create external entity parser");
8266
8267 reallocation_count = (intptr_t)XML_GetUserData(parser);
8268 buffer = XML_GetBuffer(ext_parser, 1536);
8269 if (buffer == NULL)
8270 fail("Buffer allocation failed");
8271 assert(buffer != NULL);
8272 memcpy(buffer, text, strlen(text));
8273 status = XML_ParseBuffer(ext_parser, (int)strlen(text), XML_FALSE);
8274 reallocation_count = -1;
8275 XML_ParserFree(ext_parser);
8276 return (status == XML_STATUS_OK) ? XML_STATUS_OK : XML_STATUS_ERROR;
8277 }
8278
START_TEST(test_alloc_ext_entity_realloc_buffer)8279 START_TEST(test_alloc_ext_entity_realloc_buffer) {
8280 const char *text = "<!DOCTYPE doc [\n"
8281 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
8282 "]>\n"
8283 "<doc>&en;</doc>";
8284 int i;
8285 const int max_realloc_count = 10;
8286
8287 for (i = 0; i < max_realloc_count; i++) {
8288 XML_SetExternalEntityRefHandler(g_parser, external_entity_reallocator);
8289 XML_SetUserData(g_parser, (void *)(intptr_t)i);
8290 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8291 == XML_STATUS_OK)
8292 break;
8293 /* See comment in test_alloc_parse_xdecl() */
8294 alloc_teardown();
8295 alloc_setup();
8296 }
8297 if (i == 0)
8298 fail("Succeeded with no reallocations");
8299 if (i == max_realloc_count)
8300 fail("Failed with max reallocations");
8301 }
8302 END_TEST
8303
8304 /* Test elements with many attributes are handled correctly */
START_TEST(test_alloc_realloc_many_attributes)8305 START_TEST(test_alloc_realloc_many_attributes) {
8306 const char *text = "<!DOCTYPE doc [\n"
8307 "<!ATTLIST doc za CDATA 'default'>\n"
8308 "<!ATTLIST doc zb CDATA 'def2'>\n"
8309 "<!ATTLIST doc zc CDATA 'def3'>\n"
8310 "]>\n"
8311 "<doc a='1'"
8312 " b='2'"
8313 " c='3'"
8314 " d='4'"
8315 " e='5'"
8316 " f='6'"
8317 " g='7'"
8318 " h='8'"
8319 " i='9'"
8320 " j='10'"
8321 " k='11'"
8322 " l='12'"
8323 " m='13'"
8324 " n='14'"
8325 " p='15'"
8326 " q='16'"
8327 " r='17'"
8328 " s='18'>"
8329 "</doc>";
8330 int i;
8331 const int max_realloc_count = 10;
8332
8333 for (i = 0; i < max_realloc_count; i++) {
8334 reallocation_count = i;
8335 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8336 != XML_STATUS_ERROR)
8337 break;
8338 /* See comment in test_alloc_parse_xdecl() */
8339 alloc_teardown();
8340 alloc_setup();
8341 }
8342 if (i == 0)
8343 fail("Parse succeeded despite no reallocations");
8344 if (i == max_realloc_count)
8345 fail("Parse failed at max reallocations");
8346 }
8347 END_TEST
8348
8349 /* Test handling of a public entity with failing allocator */
START_TEST(test_alloc_public_entity_value)8350 START_TEST(test_alloc_public_entity_value) {
8351 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
8352 "<doc></doc>\n";
8353 char dtd_text[]
8354 = "<!ELEMENT doc EMPTY>\n"
8355 "<!ENTITY % e1 PUBLIC 'foo' 'bar.ent'>\n"
8356 "<!ENTITY % "
8357 /* Each line is 64 characters */
8358 "ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345"
8359 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8360 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8361 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8362 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8363 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8364 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8365 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8366 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8367 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8368 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8369 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8370 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8371 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8372 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8373 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8374 " '%e1;'>\n"
8375 "%e1;\n";
8376 int i;
8377 const int max_alloc_count = 50;
8378
8379 for (i = 0; i < max_alloc_count; i++) {
8380 allocation_count = i;
8381 dummy_handler_flags = 0;
8382 XML_SetUserData(g_parser, dtd_text);
8383 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8384 XML_SetExternalEntityRefHandler(g_parser, external_entity_public);
8385 /* Provoke a particular code path */
8386 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
8387 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8388 != XML_STATUS_ERROR)
8389 break;
8390 /* See comment in test_alloc_parse_xdecl() */
8391 alloc_teardown();
8392 alloc_setup();
8393 }
8394 if (i == 0)
8395 fail("Parsing worked despite failing allocation");
8396 if (i == max_alloc_count)
8397 fail("Parsing failed at max allocation count");
8398 if (dummy_handler_flags != DUMMY_ENTITY_DECL_HANDLER_FLAG)
8399 fail("Entity declaration handler not called");
8400 }
8401 END_TEST
8402
START_TEST(test_alloc_realloc_subst_public_entity_value)8403 START_TEST(test_alloc_realloc_subst_public_entity_value) {
8404 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
8405 "<doc></doc>\n";
8406 char dtd_text[]
8407 = "<!ELEMENT doc EMPTY>\n"
8408 "<!ENTITY % "
8409 /* Each line is 64 characters */
8410 "ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345"
8411 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8412 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8413 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8414 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8415 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8416 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8417 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8418 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8419 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8420 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8421 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8422 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8423 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8424 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8425 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8426 " PUBLIC 'foo' 'bar.ent'>\n"
8427 "%ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345"
8428 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8429 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8430 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8431 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8432 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8433 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8434 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8435 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8436 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8437 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8438 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8439 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8440 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8441 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8442 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP;";
8443 int i;
8444 const int max_realloc_count = 10;
8445
8446 for (i = 0; i < max_realloc_count; i++) {
8447 reallocation_count = i;
8448 XML_SetUserData(g_parser, dtd_text);
8449 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8450 XML_SetExternalEntityRefHandler(g_parser, external_entity_public);
8451 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8452 != XML_STATUS_ERROR)
8453 break;
8454 /* See comment in test_alloc_parse_xdecl() */
8455 alloc_teardown();
8456 alloc_setup();
8457 }
8458 if (i == 0)
8459 fail("Parsing worked despite failing reallocation");
8460 if (i == max_realloc_count)
8461 fail("Parsing failed at max reallocation count");
8462 }
8463 END_TEST
8464
START_TEST(test_alloc_parse_public_doctype)8465 START_TEST(test_alloc_parse_public_doctype) {
8466 const char *text
8467 = "<?xml version='1.0' encoding='utf-8'?>\n"
8468 "<!DOCTYPE doc PUBLIC '"
8469 /* 64 characters per line */
8470 "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/"
8471 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8472 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8473 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8474 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8475 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8476 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8477 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8478 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8479 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8480 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8481 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8482 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8483 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8484 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8485 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8486 "' 'test'>\n"
8487 "<doc></doc>";
8488 int i;
8489 const int max_alloc_count = 25;
8490
8491 for (i = 0; i < max_alloc_count; i++) {
8492 allocation_count = i;
8493 dummy_handler_flags = 0;
8494 XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_decl_handler,
8495 dummy_end_doctype_decl_handler);
8496 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8497 != XML_STATUS_ERROR)
8498 break;
8499 /* See comment in test_alloc_parse_xdecl() */
8500 alloc_teardown();
8501 alloc_setup();
8502 }
8503 if (i == 0)
8504 fail("Parse succeeded despite failing allocator");
8505 if (i == max_alloc_count)
8506 fail("Parse failed at maximum allocation count");
8507 if (dummy_handler_flags
8508 != (DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG
8509 | DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG))
8510 fail("Doctype handler functions not called");
8511 }
8512 END_TEST
8513
START_TEST(test_alloc_parse_public_doctype_long_name)8514 START_TEST(test_alloc_parse_public_doctype_long_name) {
8515 const char *text
8516 = "<?xml version='1.0' encoding='utf-8'?>\n"
8517 "<!DOCTYPE doc PUBLIC 'http://example.com/foo' '"
8518 /* 64 characters per line */
8519 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8520 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8521 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8522 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8523 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8524 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8525 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8526 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8527 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8528 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8529 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8530 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8531 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8532 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8533 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8534 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8535 "'>\n"
8536 "<doc></doc>";
8537 int i;
8538 const int max_alloc_count = 25;
8539
8540 for (i = 0; i < max_alloc_count; i++) {
8541 allocation_count = i;
8542 XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_decl_handler,
8543 dummy_end_doctype_decl_handler);
8544 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8545 != XML_STATUS_ERROR)
8546 break;
8547 /* See comment in test_alloc_parse_xdecl() */
8548 alloc_teardown();
8549 alloc_setup();
8550 }
8551 if (i == 0)
8552 fail("Parse succeeded despite failing allocator");
8553 if (i == max_alloc_count)
8554 fail("Parse failed at maximum allocation count");
8555 }
8556 END_TEST
8557
8558 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)8559 external_entity_alloc(XML_Parser parser, const XML_Char *context,
8560 const XML_Char *base, const XML_Char *systemId,
8561 const XML_Char *publicId) {
8562 const char *text = (const char *)XML_GetUserData(parser);
8563 XML_Parser ext_parser;
8564 int parse_res;
8565
8566 UNUSED_P(base);
8567 UNUSED_P(systemId);
8568 UNUSED_P(publicId);
8569 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8570 if (ext_parser == NULL)
8571 return XML_STATUS_ERROR;
8572 parse_res
8573 = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
8574 XML_ParserFree(ext_parser);
8575 return parse_res;
8576 }
8577
8578 /* Test foreign DTD handling */
START_TEST(test_alloc_set_foreign_dtd)8579 START_TEST(test_alloc_set_foreign_dtd) {
8580 const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n"
8581 "<doc>&entity;</doc>";
8582 char text2[] = "<!ELEMENT doc (#PCDATA)*>";
8583 int i;
8584 const int max_alloc_count = 25;
8585
8586 for (i = 0; i < max_alloc_count; i++) {
8587 allocation_count = i;
8588 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8589 XML_SetUserData(g_parser, &text2);
8590 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
8591 if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE)
8592 fail("Could not set foreign DTD");
8593 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_TRUE)
8594 != XML_STATUS_ERROR)
8595 break;
8596 /* See comment in test_alloc_parse_xdecl() */
8597 alloc_teardown();
8598 alloc_setup();
8599 }
8600 if (i == 0)
8601 fail("Parse succeeded despite failing allocator");
8602 if (i == max_alloc_count)
8603 fail("Parse failed at maximum allocation count");
8604 }
8605 END_TEST
8606
8607 /* Test based on ibm/valid/P32/ibm32v04.xml */
START_TEST(test_alloc_attribute_enum_value)8608 START_TEST(test_alloc_attribute_enum_value) {
8609 const char *text = "<?xml version='1.0' standalone='no'?>\n"
8610 "<!DOCTYPE animal SYSTEM 'test.dtd'>\n"
8611 "<animal>This is a \n <a/> \n\nyellow tiger</animal>";
8612 char dtd_text[] = "<!ELEMENT animal (#PCDATA|a)*>\n"
8613 "<!ELEMENT a EMPTY>\n"
8614 "<!ATTLIST animal xml:space (default|preserve) 'preserve'>";
8615 int i;
8616 const int max_alloc_count = 30;
8617
8618 for (i = 0; i < max_alloc_count; i++) {
8619 allocation_count = i;
8620 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
8621 XML_SetUserData(g_parser, dtd_text);
8622 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8623 /* An attribute list handler provokes a different code path */
8624 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
8625 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8626 != XML_STATUS_ERROR)
8627 break;
8628 /* See comment in test_alloc_parse_xdecl() */
8629 alloc_teardown();
8630 alloc_setup();
8631 }
8632 if (i == 0)
8633 fail("Parse succeeded despite failing allocator");
8634 if (i == max_alloc_count)
8635 fail("Parse failed at maximum allocation count");
8636 }
8637 END_TEST
8638
8639 /* Test attribute enums sufficient to overflow the string pool */
START_TEST(test_alloc_realloc_attribute_enum_value)8640 START_TEST(test_alloc_realloc_attribute_enum_value) {
8641 const char *text = "<?xml version='1.0' standalone='no'?>\n"
8642 "<!DOCTYPE animal SYSTEM 'test.dtd'>\n"
8643 "<animal>This is a yellow tiger</animal>";
8644 /* We wish to define a collection of attribute enums that will
8645 * cause the string pool storing them to have to expand. This
8646 * means more than 1024 bytes, including the parentheses and
8647 * separator bars.
8648 */
8649 char dtd_text[]
8650 = "<!ELEMENT animal (#PCDATA)*>\n"
8651 "<!ATTLIST animal thing "
8652 "(default"
8653 /* Each line is 64 characters */
8654 "|ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8655 "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8656 "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8657 "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8658 "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8659 "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8660 "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8661 "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8662 "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8663 "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8664 "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8665 "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8666 "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8667 "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8668 "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8669 "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO)"
8670 " 'default'>";
8671 int i;
8672 const int max_realloc_count = 10;
8673
8674 for (i = 0; i < max_realloc_count; i++) {
8675 reallocation_count = i;
8676 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
8677 XML_SetUserData(g_parser, dtd_text);
8678 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8679 /* An attribute list handler provokes a different code path */
8680 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
8681 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8682 != XML_STATUS_ERROR)
8683 break;
8684 /* See comment in test_alloc_parse_xdecl() */
8685 alloc_teardown();
8686 alloc_setup();
8687 }
8688 if (i == 0)
8689 fail("Parse succeeded despite failing reallocator");
8690 if (i == max_realloc_count)
8691 fail("Parse failed at maximum reallocation count");
8692 }
8693 END_TEST
8694
8695 /* Test attribute enums in a #IMPLIED attribute forcing pool growth */
START_TEST(test_alloc_realloc_implied_attribute)8696 START_TEST(test_alloc_realloc_implied_attribute) {
8697 /* Forcing this particular code path is a balancing act. The
8698 * addition of the closing parenthesis and terminal NUL must be
8699 * what pushes the string of enums over the 1024-byte limit,
8700 * otherwise a different code path will pick up the realloc.
8701 */
8702 const char *text
8703 = "<!DOCTYPE doc [\n"
8704 "<!ELEMENT doc EMPTY>\n"
8705 "<!ATTLIST doc a "
8706 /* Each line is 64 characters */
8707 "(ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8708 "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8709 "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8710 "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8711 "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8712 "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8713 "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8714 "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8715 "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8716 "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8717 "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8718 "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8719 "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8720 "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8721 "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8722 "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN)"
8723 " #IMPLIED>\n"
8724 "]><doc/>";
8725 int i;
8726 const int max_realloc_count = 10;
8727
8728 for (i = 0; i < max_realloc_count; i++) {
8729 reallocation_count = i;
8730 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
8731 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8732 != XML_STATUS_ERROR)
8733 break;
8734 /* See comment in test_alloc_parse_xdecl() */
8735 alloc_teardown();
8736 alloc_setup();
8737 }
8738 if (i == 0)
8739 fail("Parse succeeded despite failing reallocator");
8740 if (i == max_realloc_count)
8741 fail("Parse failed at maximum reallocation count");
8742 }
8743 END_TEST
8744
8745 /* Test attribute enums in a defaulted attribute forcing pool growth */
START_TEST(test_alloc_realloc_default_attribute)8746 START_TEST(test_alloc_realloc_default_attribute) {
8747 /* Forcing this particular code path is a balancing act. The
8748 * addition of the closing parenthesis and terminal NUL must be
8749 * what pushes the string of enums over the 1024-byte limit,
8750 * otherwise a different code path will pick up the realloc.
8751 */
8752 const char *text
8753 = "<!DOCTYPE doc [\n"
8754 "<!ELEMENT doc EMPTY>\n"
8755 "<!ATTLIST doc a "
8756 /* Each line is 64 characters */
8757 "(ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8758 "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8759 "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8760 "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8761 "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8762 "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8763 "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8764 "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8765 "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8766 "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8767 "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8768 "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8769 "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8770 "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8771 "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8772 "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN)"
8773 " 'ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO'"
8774 ">\n]><doc/>";
8775 int i;
8776 const int max_realloc_count = 10;
8777
8778 for (i = 0; i < max_realloc_count; i++) {
8779 reallocation_count = i;
8780 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
8781 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8782 != XML_STATUS_ERROR)
8783 break;
8784 /* See comment in test_alloc_parse_xdecl() */
8785 alloc_teardown();
8786 alloc_setup();
8787 }
8788 if (i == 0)
8789 fail("Parse succeeded despite failing reallocator");
8790 if (i == max_realloc_count)
8791 fail("Parse failed at maximum reallocation count");
8792 }
8793 END_TEST
8794
8795 /* Test long notation name with dodgy allocator */
START_TEST(test_alloc_notation)8796 START_TEST(test_alloc_notation) {
8797 const char *text
8798 = "<!DOCTYPE doc [\n"
8799 "<!NOTATION "
8800 /* Each line is 64 characters */
8801 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8802 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8803 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8804 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8805 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8806 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8807 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8808 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8809 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8810 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8811 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8812 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8813 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8814 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8815 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8816 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8817 " SYSTEM 'http://example.org/n'>\n"
8818 "<!ENTITY e SYSTEM 'http://example.org/e' NDATA "
8819 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8820 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8821 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8822 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8823 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8824 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8825 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8826 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8827 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8828 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8829 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8830 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8831 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8832 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8833 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8834 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8835 ">\n"
8836 "<!ELEMENT doc EMPTY>\n"
8837 "]>\n<doc/>";
8838 int i;
8839 const int max_alloc_count = 20;
8840
8841 for (i = 0; i < max_alloc_count; i++) {
8842 allocation_count = i;
8843 dummy_handler_flags = 0;
8844 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
8845 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
8846 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8847 != XML_STATUS_ERROR)
8848 break;
8849 /* See comment in test_alloc_parse_xdecl() */
8850 alloc_teardown();
8851 alloc_setup();
8852 }
8853 if (i == 0)
8854 fail("Parse succeeded despite allocation failures");
8855 if (i == max_alloc_count)
8856 fail("Parse failed at maximum allocation count");
8857 if (dummy_handler_flags
8858 != (DUMMY_ENTITY_DECL_HANDLER_FLAG | DUMMY_NOTATION_DECL_HANDLER_FLAG))
8859 fail("Entity declaration handler not called");
8860 }
8861 END_TEST
8862
8863 /* Test public notation with dodgy allocator */
START_TEST(test_alloc_public_notation)8864 START_TEST(test_alloc_public_notation) {
8865 const char *text
8866 = "<!DOCTYPE doc [\n"
8867 "<!NOTATION note PUBLIC '"
8868 /* 64 characters per line */
8869 "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/"
8870 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8871 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8872 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8873 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8874 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8875 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8876 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8877 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8878 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8879 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8880 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8881 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8882 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8883 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8884 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8885 "' 'foo'>\n"
8886 "<!ENTITY e SYSTEM 'http://example.com/e' NDATA note>\n"
8887 "<!ELEMENT doc EMPTY>\n"
8888 "]>\n<doc/>";
8889 int i;
8890 const int max_alloc_count = 20;
8891
8892 for (i = 0; i < max_alloc_count; i++) {
8893 allocation_count = i;
8894 dummy_handler_flags = 0;
8895 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
8896 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8897 != XML_STATUS_ERROR)
8898 break;
8899 /* See comment in test_alloc_parse_xdecl() */
8900 alloc_teardown();
8901 alloc_setup();
8902 }
8903 if (i == 0)
8904 fail("Parse succeeded despite allocation failures");
8905 if (i == max_alloc_count)
8906 fail("Parse failed at maximum allocation count");
8907 if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG)
8908 fail("Notation handler not called");
8909 }
8910 END_TEST
8911
8912 /* Test public notation with dodgy allocator */
START_TEST(test_alloc_system_notation)8913 START_TEST(test_alloc_system_notation) {
8914 const char *text
8915 = "<!DOCTYPE doc [\n"
8916 "<!NOTATION note SYSTEM '"
8917 /* 64 characters per line */
8918 "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/"
8919 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8920 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8921 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8922 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8923 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8924 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8925 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8926 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8927 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8928 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8929 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8930 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8931 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8932 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8933 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8934 "'>\n"
8935 "<!ENTITY e SYSTEM 'http://example.com/e' NDATA note>\n"
8936 "<!ELEMENT doc EMPTY>\n"
8937 "]>\n<doc/>";
8938 int i;
8939 const int max_alloc_count = 20;
8940
8941 for (i = 0; i < max_alloc_count; i++) {
8942 allocation_count = i;
8943 dummy_handler_flags = 0;
8944 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
8945 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8946 != XML_STATUS_ERROR)
8947 break;
8948 /* See comment in test_alloc_parse_xdecl() */
8949 alloc_teardown();
8950 alloc_setup();
8951 }
8952 if (i == 0)
8953 fail("Parse succeeded despite allocation failures");
8954 if (i == max_alloc_count)
8955 fail("Parse failed at maximum allocation count");
8956 if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG)
8957 fail("Notation handler not called");
8958 }
8959 END_TEST
8960
START_TEST(test_alloc_nested_groups)8961 START_TEST(test_alloc_nested_groups) {
8962 const char *text
8963 = "<!DOCTYPE doc [\n"
8964 "<!ELEMENT doc "
8965 /* Sixteen elements per line */
8966 "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,"
8967 "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?"
8968 "))))))))))))))))))))))))))))))))>\n"
8969 "<!ELEMENT e EMPTY>"
8970 "]>\n"
8971 "<doc><e/></doc>";
8972 CharData storage;
8973 int i;
8974 const int max_alloc_count = 20;
8975
8976 for (i = 0; i < max_alloc_count; i++) {
8977 allocation_count = i;
8978 CharData_Init(&storage);
8979 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
8980 XML_SetStartElementHandler(g_parser, record_element_start_handler);
8981 XML_SetUserData(g_parser, &storage);
8982 dummy_handler_flags = 0;
8983 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8984 != XML_STATUS_ERROR)
8985 break;
8986 /* See comment in test_alloc_parse_xdecl() */
8987 alloc_teardown();
8988 alloc_setup();
8989 }
8990
8991 if (i == 0)
8992 fail("Parse succeeded despite failing reallocator");
8993 if (i == max_alloc_count)
8994 fail("Parse failed at maximum reallocation count");
8995 CharData_CheckXMLChars(&storage, XCS("doce"));
8996 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
8997 fail("Element handler not fired");
8998 }
8999 END_TEST
9000
START_TEST(test_alloc_realloc_nested_groups)9001 START_TEST(test_alloc_realloc_nested_groups) {
9002 const char *text
9003 = "<!DOCTYPE doc [\n"
9004 "<!ELEMENT doc "
9005 /* Sixteen elements per line */
9006 "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,"
9007 "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?"
9008 "))))))))))))))))))))))))))))))))>\n"
9009 "<!ELEMENT e EMPTY>"
9010 "]>\n"
9011 "<doc><e/></doc>";
9012 CharData storage;
9013 int i;
9014 const int max_realloc_count = 10;
9015
9016 for (i = 0; i < max_realloc_count; i++) {
9017 reallocation_count = i;
9018 CharData_Init(&storage);
9019 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
9020 XML_SetStartElementHandler(g_parser, record_element_start_handler);
9021 XML_SetUserData(g_parser, &storage);
9022 dummy_handler_flags = 0;
9023 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9024 != XML_STATUS_ERROR)
9025 break;
9026 /* See comment in test_alloc_parse_xdecl() */
9027 alloc_teardown();
9028 alloc_setup();
9029 }
9030
9031 if (i == 0)
9032 fail("Parse succeeded despite failing reallocator");
9033 if (i == max_realloc_count)
9034 fail("Parse failed at maximum reallocation count");
9035 CharData_CheckXMLChars(&storage, XCS("doce"));
9036 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9037 fail("Element handler not fired");
9038 }
9039 END_TEST
9040
START_TEST(test_alloc_large_group)9041 START_TEST(test_alloc_large_group) {
9042 const char *text = "<!DOCTYPE doc [\n"
9043 "<!ELEMENT doc ("
9044 "a1|a2|a3|a4|a5|a6|a7|a8|"
9045 "b1|b2|b3|b4|b5|b6|b7|b8|"
9046 "c1|c2|c3|c4|c5|c6|c7|c8|"
9047 "d1|d2|d3|d4|d5|d6|d7|d8|"
9048 "e1"
9049 ")+>\n"
9050 "]>\n"
9051 "<doc>\n"
9052 "<a1/>\n"
9053 "</doc>\n";
9054 int i;
9055 const int max_alloc_count = 50;
9056
9057 for (i = 0; i < max_alloc_count; i++) {
9058 allocation_count = i;
9059 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
9060 dummy_handler_flags = 0;
9061 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9062 != XML_STATUS_ERROR)
9063 break;
9064 /* See comment in test_alloc_parse_xdecl() */
9065 alloc_teardown();
9066 alloc_setup();
9067 }
9068 if (i == 0)
9069 fail("Parse succeeded despite failing allocator");
9070 if (i == max_alloc_count)
9071 fail("Parse failed at maximum allocation count");
9072 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9073 fail("Element handler flag not raised");
9074 }
9075 END_TEST
9076
START_TEST(test_alloc_realloc_group_choice)9077 START_TEST(test_alloc_realloc_group_choice) {
9078 const char *text = "<!DOCTYPE doc [\n"
9079 "<!ELEMENT doc ("
9080 "a1|a2|a3|a4|a5|a6|a7|a8|"
9081 "b1|b2|b3|b4|b5|b6|b7|b8|"
9082 "c1|c2|c3|c4|c5|c6|c7|c8|"
9083 "d1|d2|d3|d4|d5|d6|d7|d8|"
9084 "e1"
9085 ")+>\n"
9086 "]>\n"
9087 "<doc>\n"
9088 "<a1/>\n"
9089 "<b2 attr='foo'>This is a foo</b2>\n"
9090 "<c3></c3>\n"
9091 "</doc>\n";
9092 int i;
9093 const int max_realloc_count = 10;
9094
9095 for (i = 0; i < max_realloc_count; i++) {
9096 reallocation_count = i;
9097 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
9098 dummy_handler_flags = 0;
9099 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9100 != XML_STATUS_ERROR)
9101 break;
9102 /* See comment in test_alloc_parse_xdecl() */
9103 alloc_teardown();
9104 alloc_setup();
9105 }
9106 if (i == 0)
9107 fail("Parse succeeded despite failing reallocator");
9108 if (i == max_realloc_count)
9109 fail("Parse failed at maximum reallocation count");
9110 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9111 fail("Element handler flag not raised");
9112 }
9113 END_TEST
9114
START_TEST(test_alloc_pi_in_epilog)9115 START_TEST(test_alloc_pi_in_epilog) {
9116 const char *text = "<doc></doc>\n"
9117 "<?pi in epilog?>";
9118 int i;
9119 const int max_alloc_count = 15;
9120
9121 for (i = 0; i < max_alloc_count; i++) {
9122 allocation_count = i;
9123 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
9124 dummy_handler_flags = 0;
9125 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9126 != XML_STATUS_ERROR)
9127 break;
9128 /* See comment in test_alloc_parse_xdecl() */
9129 alloc_teardown();
9130 alloc_setup();
9131 }
9132 if (i == 0)
9133 fail("Parse completed despite failing allocator");
9134 if (i == max_alloc_count)
9135 fail("Parse failed at maximum allocation count");
9136 if (dummy_handler_flags != DUMMY_PI_HANDLER_FLAG)
9137 fail("Processing instruction handler not invoked");
9138 }
9139 END_TEST
9140
START_TEST(test_alloc_comment_in_epilog)9141 START_TEST(test_alloc_comment_in_epilog) {
9142 const char *text = "<doc></doc>\n"
9143 "<!-- comment in epilog -->";
9144 int i;
9145 const int max_alloc_count = 15;
9146
9147 for (i = 0; i < max_alloc_count; i++) {
9148 allocation_count = i;
9149 XML_SetCommentHandler(g_parser, dummy_comment_handler);
9150 dummy_handler_flags = 0;
9151 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9152 != XML_STATUS_ERROR)
9153 break;
9154 /* See comment in test_alloc_parse_xdecl() */
9155 alloc_teardown();
9156 alloc_setup();
9157 }
9158 if (i == 0)
9159 fail("Parse completed despite failing allocator");
9160 if (i == max_alloc_count)
9161 fail("Parse failed at maximum allocation count");
9162 if (dummy_handler_flags != DUMMY_COMMENT_HANDLER_FLAG)
9163 fail("Processing instruction handler not invoked");
9164 }
9165 END_TEST
9166
START_TEST(test_alloc_realloc_long_attribute_value)9167 START_TEST(test_alloc_realloc_long_attribute_value) {
9168 const char *text
9169 = "<!DOCTYPE doc [<!ENTITY foo '"
9170 /* Each line is 64 characters */
9171 "This entity will be substituted as an attribute value, and is "
9172 "calculated to be exactly long enough that the terminating NUL "
9173 "that the library adds internally will trigger the string pool to"
9174 "grow. GHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9175 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9176 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9177 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9178 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9179 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9180 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9181 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9182 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9183 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9184 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9185 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9186 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9187 "'>]>\n"
9188 "<doc a='&foo;'></doc>";
9189 int i;
9190 const int max_realloc_count = 10;
9191
9192 for (i = 0; i < max_realloc_count; i++) {
9193 reallocation_count = i;
9194 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9195 != XML_STATUS_ERROR)
9196 break;
9197 /* See comment in test_alloc_parse_xdecl() */
9198 alloc_teardown();
9199 alloc_setup();
9200 }
9201 if (i == 0)
9202 fail("Parse succeeded despite failing reallocator");
9203 if (i == max_realloc_count)
9204 fail("Parse failed at maximum reallocation count");
9205 }
9206 END_TEST
9207
START_TEST(test_alloc_attribute_whitespace)9208 START_TEST(test_alloc_attribute_whitespace) {
9209 const char *text = "<doc a=' '></doc>";
9210 int i;
9211 const int max_alloc_count = 15;
9212
9213 for (i = 0; i < max_alloc_count; i++) {
9214 allocation_count = i;
9215 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9216 != XML_STATUS_ERROR)
9217 break;
9218 /* See comment in test_alloc_parse_xdecl() */
9219 alloc_teardown();
9220 alloc_setup();
9221 }
9222 if (i == 0)
9223 fail("Parse succeeded despite failing allocator");
9224 if (i == max_alloc_count)
9225 fail("Parse failed at maximum allocation count");
9226 }
9227 END_TEST
9228
START_TEST(test_alloc_attribute_predefined_entity)9229 START_TEST(test_alloc_attribute_predefined_entity) {
9230 const char *text = "<doc a='&'></doc>";
9231 int i;
9232 const int max_alloc_count = 15;
9233
9234 for (i = 0; i < max_alloc_count; i++) {
9235 allocation_count = i;
9236 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9237 != XML_STATUS_ERROR)
9238 break;
9239 /* See comment in test_alloc_parse_xdecl() */
9240 alloc_teardown();
9241 alloc_setup();
9242 }
9243 if (i == 0)
9244 fail("Parse succeeded despite failing allocator");
9245 if (i == max_alloc_count)
9246 fail("Parse failed at maximum allocation count");
9247 }
9248 END_TEST
9249
9250 /* Test that a character reference at the end of a suitably long
9251 * default value for an attribute can trigger pool growth, and recovers
9252 * if the allocator fails on it.
9253 */
START_TEST(test_alloc_long_attr_default_with_char_ref)9254 START_TEST(test_alloc_long_attr_default_with_char_ref) {
9255 const char *text
9256 = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '"
9257 /* 64 characters per line */
9258 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9259 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9260 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9261 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9262 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9263 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9264 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9265 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9266 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9267 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9268 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9269 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9270 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9271 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9272 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9273 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHI"
9274 "1'>]>\n"
9275 "<doc/>";
9276 int i;
9277 const int max_alloc_count = 20;
9278
9279 for (i = 0; i < max_alloc_count; i++) {
9280 allocation_count = i;
9281 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9282 != XML_STATUS_ERROR)
9283 break;
9284 /* See comment in test_alloc_parse_xdecl() */
9285 alloc_teardown();
9286 alloc_setup();
9287 }
9288 if (i == 0)
9289 fail("Parse succeeded despite failing allocator");
9290 if (i == max_alloc_count)
9291 fail("Parse failed at maximum allocation count");
9292 }
9293 END_TEST
9294
9295 /* Test that a long character reference substitution triggers a pool
9296 * expansion correctly for an attribute value.
9297 */
START_TEST(test_alloc_long_attr_value)9298 START_TEST(test_alloc_long_attr_value) {
9299 const char *text
9300 = "<!DOCTYPE test [<!ENTITY foo '\n"
9301 /* 64 characters per line */
9302 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9303 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9304 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9305 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9306 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9307 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9308 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9309 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9310 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9311 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9312 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9313 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9314 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9315 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9316 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9317 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9318 "'>]>\n"
9319 "<test a='&foo;'/>";
9320 int i;
9321 const int max_alloc_count = 25;
9322
9323 for (i = 0; i < max_alloc_count; i++) {
9324 allocation_count = i;
9325 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9326 != XML_STATUS_ERROR)
9327 break;
9328 /* See comment in test_alloc_parse_xdecl() */
9329 alloc_teardown();
9330 alloc_setup();
9331 }
9332 if (i == 0)
9333 fail("Parse succeeded despite failing allocator");
9334 if (i == max_alloc_count)
9335 fail("Parse failed at maximum allocation count");
9336 }
9337 END_TEST
9338
9339 /* Test that an error in a nested parameter entity substitution is
9340 * handled correctly. It seems unlikely that the code path being
9341 * exercised can be reached purely by carefully crafted XML, but an
9342 * allocation error in the right place will definitely do it.
9343 */
START_TEST(test_alloc_nested_entities)9344 START_TEST(test_alloc_nested_entities) {
9345 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n"
9346 "<doc />";
9347 ExtFaults test_data
9348 = {"<!ENTITY % pe1 '"
9349 /* 64 characters per line */
9350 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9351 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9352 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9353 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9354 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9355 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9356 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9357 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9358 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9359 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9360 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9361 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9362 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9363 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9364 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9365 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9366 "'>\n"
9367 "<!ENTITY % pe2 '%pe1;'>\n"
9368 "%pe2;",
9369 "Memory Fail not faulted", NULL, XML_ERROR_NO_MEMORY};
9370
9371 /* Causes an allocation error in a nested storeEntityValue() */
9372 allocation_count = 12;
9373 XML_SetUserData(g_parser, &test_data);
9374 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9375 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
9376 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
9377 "Entity allocation failure not noted");
9378 }
9379 END_TEST
9380
START_TEST(test_alloc_realloc_param_entity_newline)9381 START_TEST(test_alloc_realloc_param_entity_newline) {
9382 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
9383 "<doc/>";
9384 char dtd_text[]
9385 = "<!ENTITY % pe '<!ATTLIST doc att CDATA \""
9386 /* 64 characters per line */
9387 "This default value is carefully crafted so that the carriage "
9388 "return right at the end of the entity string causes an internal "
9389 "string pool to have to grow. This allows us to test the alloc "
9390 "failure path from that point. OPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9391 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9392 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9393 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9394 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9395 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9396 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9397 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9398 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9399 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9400 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9401 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9402 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDE"
9403 "\">\n'>"
9404 "%pe;\n";
9405 int i;
9406 const int max_realloc_count = 5;
9407
9408 for (i = 0; i < max_realloc_count; i++) {
9409 reallocation_count = i;
9410 XML_SetUserData(g_parser, dtd_text);
9411 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9412 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9413 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9414 != XML_STATUS_ERROR)
9415 break;
9416 /* See comment in test_alloc_parse_xdecl() */
9417 alloc_teardown();
9418 alloc_setup();
9419 }
9420 if (i == 0)
9421 fail("Parse succeeded despite failing reallocator");
9422 if (i == max_realloc_count)
9423 fail("Parse failed at maximum reallocation count");
9424 }
9425 END_TEST
9426
START_TEST(test_alloc_realloc_ce_extends_pe)9427 START_TEST(test_alloc_realloc_ce_extends_pe) {
9428 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
9429 "<doc/>";
9430 char dtd_text[]
9431 = "<!ENTITY % pe '<!ATTLIST doc att CDATA \""
9432 /* 64 characters per line */
9433 "This default value is carefully crafted so that the character "
9434 "entity at the end causes an internal string pool to have to "
9435 "grow. This allows us to test the allocation failure path from "
9436 "that point onwards. EFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9437 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9438 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9439 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9440 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9441 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9442 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9443 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9444 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9445 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9446 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9447 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9448 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGQ"
9449 "\">\n'>"
9450 "%pe;\n";
9451 int i;
9452 const int max_realloc_count = 5;
9453
9454 for (i = 0; i < max_realloc_count; i++) {
9455 reallocation_count = i;
9456 XML_SetUserData(g_parser, dtd_text);
9457 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9458 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9459 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9460 != XML_STATUS_ERROR)
9461 break;
9462 /* See comment in test_alloc_parse_xdecl() */
9463 alloc_teardown();
9464 alloc_setup();
9465 }
9466 if (i == 0)
9467 fail("Parse succeeded despite failing reallocator");
9468 if (i == max_realloc_count)
9469 fail("Parse failed at maximum reallocation count");
9470 }
9471 END_TEST
9472
START_TEST(test_alloc_realloc_attributes)9473 START_TEST(test_alloc_realloc_attributes) {
9474 const char *text = "<!DOCTYPE doc [\n"
9475 " <!ATTLIST doc\n"
9476 " a1 (a|b|c) 'a'\n"
9477 " a2 (foo|bar) #IMPLIED\n"
9478 " a3 NMTOKEN #IMPLIED\n"
9479 " a4 NMTOKENS #IMPLIED\n"
9480 " a5 ID #IMPLIED\n"
9481 " a6 IDREF #IMPLIED\n"
9482 " a7 IDREFS #IMPLIED\n"
9483 " a8 ENTITY #IMPLIED\n"
9484 " a9 ENTITIES #IMPLIED\n"
9485 " a10 CDATA #IMPLIED\n"
9486 " >]>\n"
9487 "<doc>wombat</doc>\n";
9488 int i;
9489 const int max_realloc_count = 5;
9490
9491 for (i = 0; i < max_realloc_count; i++) {
9492 reallocation_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
9501 if (i == 0)
9502 fail("Parse succeeded despite failing reallocator");
9503 if (i == max_realloc_count)
9504 fail("Parse failed at maximum reallocation count");
9505 }
9506 END_TEST
9507
START_TEST(test_alloc_long_doc_name)9508 START_TEST(test_alloc_long_doc_name) {
9509 const char *text =
9510 /* 64 characters per line */
9511 "<LongRootElementNameThatWillCauseTheNextAllocationToExpandTheStr"
9512 "ingPoolForTheDTDQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9513 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9514 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9515 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9516 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9517 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9518 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9519 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9520 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9521 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9522 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9523 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9524 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9525 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9526 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9527 " a='1'/>";
9528 int i;
9529 const int max_alloc_count = 20;
9530
9531 for (i = 0; i < max_alloc_count; i++) {
9532 allocation_count = i;
9533 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9534 != XML_STATUS_ERROR)
9535 break;
9536 /* See comment in test_alloc_parse_xdecl() */
9537 alloc_teardown();
9538 alloc_setup();
9539 }
9540 if (i == 0)
9541 fail("Parsing worked despite failing reallocations");
9542 else if (i == max_alloc_count)
9543 fail("Parsing failed even at max reallocation count");
9544 }
9545 END_TEST
9546
START_TEST(test_alloc_long_base)9547 START_TEST(test_alloc_long_base) {
9548 const char *text = "<!DOCTYPE doc [\n"
9549 " <!ENTITY e SYSTEM 'foo'>\n"
9550 "]>\n"
9551 "<doc>&e;</doc>";
9552 char entity_text[] = "Hello world";
9553 const XML_Char *base =
9554 /* 64 characters per line */
9555 /* clang-format off */
9556 XCS("LongBaseURI/that/will/overflow/an/internal/buffer/and/cause/it/t")
9557 XCS("o/have/to/grow/PQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9558 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9559 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9560 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9561 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9562 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9563 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9564 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9565 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9566 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9567 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9568 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9569 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9570 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9571 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/");
9572 /* clang-format on */
9573 int i;
9574 const int max_alloc_count = 25;
9575
9576 for (i = 0; i < max_alloc_count; i++) {
9577 allocation_count = i;
9578 XML_SetUserData(g_parser, entity_text);
9579 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9580 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9581 if (XML_SetBase(g_parser, base) == XML_STATUS_ERROR) {
9582 XML_ParserReset(g_parser, NULL);
9583 continue;
9584 }
9585 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9586 != XML_STATUS_ERROR)
9587 break;
9588 /* See comment in test_alloc_parse_xdecl() */
9589 alloc_teardown();
9590 alloc_setup();
9591 }
9592 if (i == 0)
9593 fail("Parsing worked despite failing allocations");
9594 else if (i == max_alloc_count)
9595 fail("Parsing failed even at max allocation count");
9596 }
9597 END_TEST
9598
START_TEST(test_alloc_long_public_id)9599 START_TEST(test_alloc_long_public_id) {
9600 const char *text
9601 = "<!DOCTYPE doc [\n"
9602 " <!ENTITY e PUBLIC '"
9603 /* 64 characters per line */
9604 "LongPublicIDThatShouldResultInAnInternalStringPoolGrowingAtASpec"
9605 "ificMomentKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9606 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9607 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9608 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9609 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9610 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9611 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9612 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9613 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9614 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9615 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9616 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9617 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9618 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9619 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9620 "' 'bar'>\n"
9621 "]>\n"
9622 "<doc>&e;</doc>";
9623 char entity_text[] = "Hello world";
9624 int i;
9625 const int max_alloc_count = 40;
9626
9627 for (i = 0; i < max_alloc_count; i++) {
9628 allocation_count = i;
9629 XML_SetUserData(g_parser, entity_text);
9630 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9631 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9632 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9633 != XML_STATUS_ERROR)
9634 break;
9635 /* See comment in test_alloc_parse_xdecl() */
9636 alloc_teardown();
9637 alloc_setup();
9638 }
9639 if (i == 0)
9640 fail("Parsing worked despite failing allocations");
9641 else if (i == max_alloc_count)
9642 fail("Parsing failed even at max allocation count");
9643 }
9644 END_TEST
9645
START_TEST(test_alloc_long_entity_value)9646 START_TEST(test_alloc_long_entity_value) {
9647 const char *text
9648 = "<!DOCTYPE doc [\n"
9649 " <!ENTITY e1 '"
9650 /* 64 characters per line */
9651 "Long entity value that should provoke a string pool to grow whil"
9652 "e setting up to parse the external entity below. xyz0123456789AB"
9653 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9654 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9655 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9656 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9657 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9658 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9659 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9660 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9661 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9662 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9663 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9664 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9665 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9666 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9667 "'>\n"
9668 " <!ENTITY e2 SYSTEM 'bar'>\n"
9669 "]>\n"
9670 "<doc>&e2;</doc>";
9671 char entity_text[] = "Hello world";
9672 int i;
9673 const int max_alloc_count = 40;
9674
9675 for (i = 0; i < max_alloc_count; i++) {
9676 allocation_count = i;
9677 XML_SetUserData(g_parser, entity_text);
9678 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9679 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9680 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9681 != XML_STATUS_ERROR)
9682 break;
9683 /* See comment in test_alloc_parse_xdecl() */
9684 alloc_teardown();
9685 alloc_setup();
9686 }
9687 if (i == 0)
9688 fail("Parsing worked despite failing allocations");
9689 else if (i == max_alloc_count)
9690 fail("Parsing failed even at max allocation count");
9691 }
9692 END_TEST
9693
START_TEST(test_alloc_long_notation)9694 START_TEST(test_alloc_long_notation) {
9695 const char *text
9696 = "<!DOCTYPE doc [\n"
9697 " <!NOTATION note SYSTEM '"
9698 /* 64 characters per line */
9699 "ALongNotationNameThatShouldProvokeStringPoolGrowthWhileCallingAn"
9700 "ExternalEntityParserUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9701 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9702 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9703 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9704 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9705 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9706 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9707 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9708 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9709 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9710 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9711 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9712 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9713 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9714 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9715 "'>\n"
9716 " <!ENTITY e1 SYSTEM 'foo' NDATA "
9717 /* 64 characters per line */
9718 "ALongNotationNameThatShouldProvokeStringPoolGrowthWhileCallingAn"
9719 "ExternalEntityParserUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9720 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9721 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9722 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9723 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9724 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9725 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9726 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9727 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9728 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9729 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9730 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9731 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9732 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9733 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9734 ">\n"
9735 " <!ENTITY e2 SYSTEM 'bar'>\n"
9736 "]>\n"
9737 "<doc>&e2;</doc>";
9738 ExtOption options[]
9739 = {{XCS("foo"), "Entity Foo"}, {XCS("bar"), "Entity Bar"}, {NULL, NULL}};
9740 int i;
9741 const int max_alloc_count = 40;
9742
9743 for (i = 0; i < max_alloc_count; i++) {
9744 allocation_count = i;
9745 XML_SetUserData(g_parser, options);
9746 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9747 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
9748 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9749 != XML_STATUS_ERROR)
9750 break;
9751
9752 /* See comment in test_alloc_parse_xdecl() */
9753 alloc_teardown();
9754 alloc_setup();
9755 }
9756 if (i == 0)
9757 fail("Parsing worked despite failing allocations");
9758 else if (i == max_alloc_count)
9759 fail("Parsing failed even at max allocation count");
9760 }
9761 END_TEST
9762
9763 static void
nsalloc_setup(void)9764 nsalloc_setup(void) {
9765 XML_Memory_Handling_Suite memsuite = {duff_allocator, duff_reallocator, free};
9766 XML_Char ns_sep[2] = {' ', '\0'};
9767
9768 /* Ensure the parser creation will go through */
9769 allocation_count = ALLOC_ALWAYS_SUCCEED;
9770 reallocation_count = REALLOC_ALWAYS_SUCCEED;
9771 g_parser = XML_ParserCreate_MM(NULL, &memsuite, ns_sep);
9772 if (g_parser == NULL)
9773 fail("Parser not created");
9774 }
9775
9776 static void
nsalloc_teardown(void)9777 nsalloc_teardown(void) {
9778 basic_teardown();
9779 }
9780
9781 /* Test the effects of allocation failure in simple namespace parsing.
9782 * Based on test_ns_default_with_empty_uri()
9783 */
START_TEST(test_nsalloc_xmlns)9784 START_TEST(test_nsalloc_xmlns) {
9785 const char *text = "<doc xmlns='http://example.org/'>\n"
9786 " <e xmlns=''/>\n"
9787 "</doc>";
9788 unsigned int i;
9789 const unsigned int max_alloc_count = 30;
9790
9791 for (i = 0; i < max_alloc_count; i++) {
9792 allocation_count = i;
9793 /* Exercise more code paths with a default handler */
9794 XML_SetDefaultHandler(g_parser, dummy_default_handler);
9795 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9796 != XML_STATUS_ERROR)
9797 break;
9798 /* Resetting the parser is insufficient, because some memory
9799 * allocations are cached within the parser. Instead we use
9800 * the teardown and setup routines to ensure that we have the
9801 * right sort of parser back in our hands.
9802 */
9803 nsalloc_teardown();
9804 nsalloc_setup();
9805 }
9806 if (i == 0)
9807 fail("Parsing worked despite failing allocations");
9808 else if (i == max_alloc_count)
9809 fail("Parsing failed even at maximum allocation count");
9810 }
9811 END_TEST
9812
9813 /* Test XML_ParseBuffer interface with namespace and a dicky allocator */
START_TEST(test_nsalloc_parse_buffer)9814 START_TEST(test_nsalloc_parse_buffer) {
9815 const char *text = "<doc>Hello</doc>";
9816 void *buffer;
9817
9818 /* Try a parse before the start of the world */
9819 /* (Exercises new code path) */
9820 allocation_count = 0;
9821 if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_ERROR)
9822 fail("Pre-init XML_ParseBuffer not faulted");
9823 if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_MEMORY)
9824 fail("Pre-init XML_ParseBuffer faulted for wrong reason");
9825
9826 /* Now with actual memory allocation */
9827 allocation_count = ALLOC_ALWAYS_SUCCEED;
9828 if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_OK)
9829 xml_failure(g_parser);
9830
9831 /* Check that resuming an unsuspended parser is faulted */
9832 if (XML_ResumeParser(g_parser) != XML_STATUS_ERROR)
9833 fail("Resuming unsuspended parser not faulted");
9834 if (XML_GetErrorCode(g_parser) != XML_ERROR_NOT_SUSPENDED)
9835 xml_failure(g_parser);
9836
9837 /* Get the parser into suspended state */
9838 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
9839 resumable = XML_TRUE;
9840 buffer = XML_GetBuffer(g_parser, (int)strlen(text));
9841 if (buffer == NULL)
9842 fail("Could not acquire parse buffer");
9843 assert(buffer != NULL);
9844 memcpy(buffer, text, strlen(text));
9845 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE)
9846 != XML_STATUS_SUSPENDED)
9847 xml_failure(g_parser);
9848 if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE)
9849 xml_failure(g_parser);
9850 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE)
9851 != XML_STATUS_ERROR)
9852 fail("Suspended XML_ParseBuffer not faulted");
9853 if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED)
9854 xml_failure(g_parser);
9855 if (XML_GetBuffer(g_parser, (int)strlen(text)) != NULL)
9856 fail("Suspended XML_GetBuffer not faulted");
9857
9858 /* Get it going again and complete the world */
9859 XML_SetCharacterDataHandler(g_parser, NULL);
9860 if (XML_ResumeParser(g_parser) != XML_STATUS_OK)
9861 xml_failure(g_parser);
9862 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE)
9863 != XML_STATUS_ERROR)
9864 fail("Post-finishing XML_ParseBuffer not faulted");
9865 if (XML_GetErrorCode(g_parser) != XML_ERROR_FINISHED)
9866 xml_failure(g_parser);
9867 if (XML_GetBuffer(g_parser, (int)strlen(text)) != NULL)
9868 fail("Post-finishing XML_GetBuffer not faulted");
9869 }
9870 END_TEST
9871
9872 /* Check handling of long prefix names (pool growth) */
START_TEST(test_nsalloc_long_prefix)9873 START_TEST(test_nsalloc_long_prefix) {
9874 const char *text
9875 = "<"
9876 /* 64 characters per line */
9877 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9878 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9879 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9880 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9881 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9882 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9883 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9884 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9885 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9886 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9887 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9888 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9889 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9890 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9891 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9892 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9893 ":foo xmlns:"
9894 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9895 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9896 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9897 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9898 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9899 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9900 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9901 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9902 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9903 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9904 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9905 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9906 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9907 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9908 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9909 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9910 "='http://example.org/'>"
9911 "</"
9912 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9913 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9914 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9915 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9916 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9917 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9918 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9919 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9920 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9921 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9922 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9923 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9924 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9925 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9926 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9927 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9928 ":foo>";
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 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9935 != XML_STATUS_ERROR)
9936 break;
9937 /* See comment in test_nsalloc_xmlns() */
9938 nsalloc_teardown();
9939 nsalloc_setup();
9940 }
9941 if (i == 0)
9942 fail("Parsing worked despite failing allocations");
9943 else if (i == max_alloc_count)
9944 fail("Parsing failed even at max allocation count");
9945 }
9946 END_TEST
9947
9948 /* Check handling of long uri names (pool growth) */
START_TEST(test_nsalloc_long_uri)9949 START_TEST(test_nsalloc_long_uri) {
9950 const char *text
9951 = "<foo:e xmlns:foo='http://example.org/"
9952 /* 64 characters per line */
9953 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9954 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9955 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9956 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9957 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9958 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9959 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9960 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9961 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9962 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9963 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9964 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9965 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9966 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9967 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9968 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9969 "' bar:a='12'\n"
9970 "xmlns:bar='http://example.org/"
9971 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9972 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9973 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9974 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9975 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9976 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9977 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9978 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9979 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9980 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9981 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9982 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9983 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9984 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9985 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9986 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9987 "'>"
9988 "</foo:e>";
9989 int i;
9990 const int max_alloc_count = 40;
9991
9992 for (i = 0; i < max_alloc_count; i++) {
9993 allocation_count = i;
9994 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9995 != XML_STATUS_ERROR)
9996 break;
9997 /* See comment in test_nsalloc_xmlns() */
9998 nsalloc_teardown();
9999 nsalloc_setup();
10000 }
10001 if (i == 0)
10002 fail("Parsing worked despite failing allocations");
10003 else if (i == max_alloc_count)
10004 fail("Parsing failed even at max allocation count");
10005 }
10006 END_TEST
10007
10008 /* Test handling of long attribute names with prefixes */
START_TEST(test_nsalloc_long_attr)10009 START_TEST(test_nsalloc_long_attr) {
10010 const char *text
10011 = "<foo:e xmlns:foo='http://example.org/' bar:"
10012 /* 64 characters per line */
10013 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10014 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10015 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10016 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10017 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10018 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10019 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10020 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10021 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10022 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10023 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10024 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10025 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10026 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10027 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10028 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10029 "='12'\n"
10030 "xmlns:bar='http://example.org/'>"
10031 "</foo:e>";
10032 int i;
10033 const int max_alloc_count = 40;
10034
10035 for (i = 0; i < max_alloc_count; i++) {
10036 allocation_count = i;
10037 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10038 != XML_STATUS_ERROR)
10039 break;
10040 /* See comment in test_nsalloc_xmlns() */
10041 nsalloc_teardown();
10042 nsalloc_setup();
10043 }
10044 if (i == 0)
10045 fail("Parsing worked despite failing allocations");
10046 else if (i == max_alloc_count)
10047 fail("Parsing failed even at max allocation count");
10048 }
10049 END_TEST
10050
10051 /* Test handling of an attribute name with a long namespace prefix */
START_TEST(test_nsalloc_long_attr_prefix)10052 START_TEST(test_nsalloc_long_attr_prefix) {
10053 const char *text
10054 = "<foo:e xmlns:foo='http://example.org/' "
10055 /* 64 characters per line */
10056 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10057 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10058 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10059 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10060 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10061 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10062 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10063 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10064 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10065 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10066 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10067 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10068 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10069 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10070 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10071 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10072 ":a='12'\n"
10073 "xmlns:"
10074 /* 64 characters per line */
10075 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10076 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10077 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10078 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10079 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10080 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10081 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10082 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10083 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10084 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10085 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10086 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10087 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10088 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10089 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10090 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10091 "='http://example.org/'>"
10092 "</foo:e>";
10093 const XML_Char *elemstr[] = {
10094 /* clang-format off */
10095 XCS("http://example.org/ e foo"),
10096 XCS("http://example.org/ a ")
10097 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10098 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10099 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10100 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10101 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10102 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10103 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10104 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10105 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10106 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10107 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10108 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10109 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10110 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10111 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10112 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10113 /* clang-format on */
10114 };
10115 int i;
10116 const int max_alloc_count = 40;
10117
10118 for (i = 0; i < max_alloc_count; i++) {
10119 allocation_count = i;
10120 XML_SetReturnNSTriplet(g_parser, XML_TRUE);
10121 XML_SetUserData(g_parser, (void *)elemstr);
10122 XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
10123 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10124 != XML_STATUS_ERROR)
10125 break;
10126 /* See comment in test_nsalloc_xmlns() */
10127 nsalloc_teardown();
10128 nsalloc_setup();
10129 }
10130 if (i == 0)
10131 fail("Parsing worked despite failing allocations");
10132 else if (i == max_alloc_count)
10133 fail("Parsing failed even at max allocation count");
10134 }
10135 END_TEST
10136
10137 /* Test attribute handling in the face of a dodgy reallocator */
START_TEST(test_nsalloc_realloc_attributes)10138 START_TEST(test_nsalloc_realloc_attributes) {
10139 const char *text = "<foo:e xmlns:foo='http://example.org/' bar:a='12'\n"
10140 " xmlns:bar='http://example.org/'>"
10141 "</foo:e>";
10142 int i;
10143 const int max_realloc_count = 10;
10144
10145 for (i = 0; i < max_realloc_count; i++) {
10146 reallocation_count = i;
10147 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10148 != XML_STATUS_ERROR)
10149 break;
10150 /* See comment in test_nsalloc_xmlns() */
10151 nsalloc_teardown();
10152 nsalloc_setup();
10153 }
10154 if (i == 0)
10155 fail("Parsing worked despite failing reallocations");
10156 else if (i == max_realloc_count)
10157 fail("Parsing failed at max reallocation count");
10158 }
10159 END_TEST
10160
10161 /* Test long element names with namespaces under a failing allocator */
START_TEST(test_nsalloc_long_element)10162 START_TEST(test_nsalloc_long_element) {
10163 const char *text
10164 = "<foo:thisisalongenoughelementnametotriggerareallocation\n"
10165 " xmlns:foo='http://example.org/' bar:a='12'\n"
10166 " xmlns:bar='http://example.org/'>"
10167 "</foo:thisisalongenoughelementnametotriggerareallocation>";
10168 const XML_Char *elemstr[]
10169 = {XCS("http://example.org/")
10170 XCS(" thisisalongenoughelementnametotriggerareallocation foo"),
10171 XCS("http://example.org/ a bar")};
10172 int i;
10173 const int max_alloc_count = 30;
10174
10175 for (i = 0; i < max_alloc_count; i++) {
10176 allocation_count = i;
10177 XML_SetReturnNSTriplet(g_parser, XML_TRUE);
10178 XML_SetUserData(g_parser, (void *)elemstr);
10179 XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
10180 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10181 != XML_STATUS_ERROR)
10182 break;
10183 /* See comment in test_nsalloc_xmlns() */
10184 nsalloc_teardown();
10185 nsalloc_setup();
10186 }
10187 if (i == 0)
10188 fail("Parsing worked despite failing reallocations");
10189 else if (i == max_alloc_count)
10190 fail("Parsing failed at max reallocation count");
10191 }
10192 END_TEST
10193
10194 /* Test the effects of reallocation failure when reassigning a
10195 * binding.
10196 *
10197 * XML_ParserReset does not free the BINDING structures used by a
10198 * parser, but instead adds them to an internal free list to be reused
10199 * as necessary. Likewise the URI buffers allocated for the binding
10200 * aren't freed, but kept attached to their existing binding. If the
10201 * new binding has a longer URI, it will need reallocation. This test
10202 * provokes that reallocation, and tests the control path if it fails.
10203 */
START_TEST(test_nsalloc_realloc_binding_uri)10204 START_TEST(test_nsalloc_realloc_binding_uri) {
10205 const char *first = "<doc xmlns='http://example.org/'>\n"
10206 " <e xmlns='' />\n"
10207 "</doc>";
10208 const char *second
10209 = "<doc xmlns='http://example.org/long/enough/URI/to/reallocate/'>\n"
10210 " <e xmlns='' />\n"
10211 "</doc>";
10212 unsigned i;
10213 const unsigned max_realloc_count = 10;
10214
10215 /* First, do a full parse that will leave bindings around */
10216 if (_XML_Parse_SINGLE_BYTES(g_parser, first, (int)strlen(first), XML_TRUE)
10217 == XML_STATUS_ERROR)
10218 xml_failure(g_parser);
10219
10220 /* Now repeat with a longer URI and a duff reallocator */
10221 for (i = 0; i < max_realloc_count; i++) {
10222 XML_ParserReset(g_parser, NULL);
10223 reallocation_count = i;
10224 if (_XML_Parse_SINGLE_BYTES(g_parser, second, (int)strlen(second), XML_TRUE)
10225 != XML_STATUS_ERROR)
10226 break;
10227 }
10228 if (i == 0)
10229 fail("Parsing worked despite failing reallocation");
10230 else if (i == max_realloc_count)
10231 fail("Parsing failed at max reallocation count");
10232 }
10233 END_TEST
10234
10235 /* Check handling of long prefix names (pool growth) */
START_TEST(test_nsalloc_realloc_long_prefix)10236 START_TEST(test_nsalloc_realloc_long_prefix) {
10237 const char *text
10238 = "<"
10239 /* 64 characters per line */
10240 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10241 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10242 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10243 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10244 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10245 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10246 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10247 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10248 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10249 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10250 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10251 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10252 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10253 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10254 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10255 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10256 ":foo xmlns:"
10257 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10258 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10259 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10260 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10261 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10262 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10263 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10264 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10265 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10266 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10267 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10268 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10269 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10270 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10271 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10272 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10273 "='http://example.org/'>"
10274 "</"
10275 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10276 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10277 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10278 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10279 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10280 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10281 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10282 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10283 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10284 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10285 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10286 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10287 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10288 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10289 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10290 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10291 ":foo>";
10292 int i;
10293 const int max_realloc_count = 12;
10294
10295 for (i = 0; i < max_realloc_count; i++) {
10296 reallocation_count = i;
10297 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10298 != XML_STATUS_ERROR)
10299 break;
10300 /* See comment in test_nsalloc_xmlns() */
10301 nsalloc_teardown();
10302 nsalloc_setup();
10303 }
10304 if (i == 0)
10305 fail("Parsing worked despite failing reallocations");
10306 else if (i == max_realloc_count)
10307 fail("Parsing failed even at max reallocation count");
10308 }
10309 END_TEST
10310
10311 /* Check handling of even long prefix names (different code path) */
START_TEST(test_nsalloc_realloc_longer_prefix)10312 START_TEST(test_nsalloc_realloc_longer_prefix) {
10313 const char *text
10314 = "<"
10315 /* 64 characters per line */
10316 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10317 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10318 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10319 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10320 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10321 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10322 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10323 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10324 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10325 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10326 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10327 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10328 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10329 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10330 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10331 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10332 "Q:foo xmlns:"
10333 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10334 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10335 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10336 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10337 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10338 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10339 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10340 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10341 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10342 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10343 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10344 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10345 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10346 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10347 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10348 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10349 "Q='http://example.org/'>"
10350 "</"
10351 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10352 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10353 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10354 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10355 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10356 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10357 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10358 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10359 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10360 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10361 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10362 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10363 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10364 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10365 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10366 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10367 "Q:foo>";
10368 int i;
10369 const int max_realloc_count = 12;
10370
10371 for (i = 0; i < max_realloc_count; i++) {
10372 reallocation_count = i;
10373 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10374 != XML_STATUS_ERROR)
10375 break;
10376 /* See comment in test_nsalloc_xmlns() */
10377 nsalloc_teardown();
10378 nsalloc_setup();
10379 }
10380 if (i == 0)
10381 fail("Parsing worked despite failing reallocations");
10382 else if (i == max_realloc_count)
10383 fail("Parsing failed even at max reallocation count");
10384 }
10385 END_TEST
10386
START_TEST(test_nsalloc_long_namespace)10387 START_TEST(test_nsalloc_long_namespace) {
10388 const char *text1
10389 = "<"
10390 /* 64 characters per line */
10391 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10392 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10393 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10394 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10395 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10396 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10397 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10398 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10399 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10400 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10401 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10402 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10403 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10404 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10405 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10406 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10407 ":e xmlns:"
10408 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10409 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10410 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10411 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10412 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10413 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10414 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10415 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10416 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10417 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10418 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10419 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10420 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10421 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10422 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10423 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10424 "='http://example.org/'>\n";
10425 const char *text2
10426 = "<"
10427 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10428 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10429 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10430 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10431 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10432 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10433 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10434 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10435 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10436 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10437 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10438 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10439 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10440 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10441 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10442 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10443 ":f "
10444 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10445 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10446 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10447 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10448 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10449 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10450 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10451 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10452 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10453 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10454 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10455 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10456 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10457 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10458 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10459 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10460 ":attr='foo'/>\n"
10461 "</"
10462 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10463 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10464 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10465 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10466 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10467 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10468 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10469 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10470 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10471 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10472 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10473 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10474 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10475 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10476 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10477 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10478 ":e>";
10479 int i;
10480 const int max_alloc_count = 40;
10481
10482 for (i = 0; i < max_alloc_count; i++) {
10483 allocation_count = i;
10484 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
10485 != XML_STATUS_ERROR
10486 && _XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2),
10487 XML_TRUE)
10488 != XML_STATUS_ERROR)
10489 break;
10490 /* See comment in test_nsalloc_xmlns() */
10491 nsalloc_teardown();
10492 nsalloc_setup();
10493 }
10494 if (i == 0)
10495 fail("Parsing worked despite failing allocations");
10496 else if (i == max_alloc_count)
10497 fail("Parsing failed even at max allocation count");
10498 }
10499 END_TEST
10500
10501 /* Using a slightly shorter namespace name provokes allocations in
10502 * slightly different places in the code.
10503 */
START_TEST(test_nsalloc_less_long_namespace)10504 START_TEST(test_nsalloc_less_long_namespace) {
10505 const char *text
10506 = "<"
10507 /* 64 characters per line */
10508 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10509 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10510 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10511 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10512 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10513 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10514 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10515 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10516 ":e xmlns:"
10517 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10518 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10519 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10520 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10521 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10522 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10523 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10524 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10525 "='http://example.org/'>\n"
10526 "<"
10527 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10528 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10529 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10530 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10531 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10532 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10533 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10534 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10535 ":f "
10536 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10537 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10538 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10539 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10540 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10541 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10542 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10543 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10544 ":att='foo'/>\n"
10545 "</"
10546 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10547 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10548 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10549 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10550 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10551 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10552 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10553 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10554 ":e>";
10555 int i;
10556 const int max_alloc_count = 40;
10557
10558 for (i = 0; i < max_alloc_count; i++) {
10559 allocation_count = i;
10560 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10561 != XML_STATUS_ERROR)
10562 break;
10563 /* See comment in test_nsalloc_xmlns() */
10564 nsalloc_teardown();
10565 nsalloc_setup();
10566 }
10567 if (i == 0)
10568 fail("Parsing worked despite failing allocations");
10569 else if (i == max_alloc_count)
10570 fail("Parsing failed even at max allocation count");
10571 }
10572 END_TEST
10573
START_TEST(test_nsalloc_long_context)10574 START_TEST(test_nsalloc_long_context) {
10575 const char *text
10576 = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10577 " <!ATTLIST doc baz ID #REQUIRED>\n"
10578 " <!ENTITY en SYSTEM 'bar'>\n"
10579 "]>\n"
10580 "<doc xmlns='http://example.org/"
10581 /* 64 characters per line */
10582 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10583 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10584 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10585 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10586 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10587 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10588 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10589 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10590 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10591 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10592 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10593 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10594 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10595 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10596 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10597 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKL"
10598 "' baz='2'>\n"
10599 "&en;"
10600 "</doc>";
10601 ExtOption options[] = {
10602 {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}};
10603 int i;
10604 const int max_alloc_count = 70;
10605
10606 for (i = 0; i < max_alloc_count; i++) {
10607 allocation_count = i;
10608 XML_SetUserData(g_parser, options);
10609 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
10610 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
10611 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10612 != XML_STATUS_ERROR)
10613 break;
10614
10615 /* See comment in test_nsalloc_xmlns() */
10616 nsalloc_teardown();
10617 nsalloc_setup();
10618 }
10619 if (i == 0)
10620 fail("Parsing worked despite failing allocations");
10621 else if (i == max_alloc_count)
10622 fail("Parsing failed even at max allocation count");
10623 }
10624 END_TEST
10625
10626 /* This function is void; it will throw a fail() on error, so if it
10627 * returns normally it must have succeeded.
10628 */
10629 static void
context_realloc_test(const char * text)10630 context_realloc_test(const char *text) {
10631 ExtOption options[] = {
10632 {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}};
10633 int i;
10634 const int max_realloc_count = 6;
10635
10636 for (i = 0; i < max_realloc_count; i++) {
10637 reallocation_count = i;
10638 XML_SetUserData(g_parser, options);
10639 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
10640 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
10641 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10642 != XML_STATUS_ERROR)
10643 break;
10644 /* See comment in test_nsalloc_xmlns() */
10645 nsalloc_teardown();
10646 nsalloc_setup();
10647 }
10648 if (i == 0)
10649 fail("Parsing worked despite failing reallocations");
10650 else if (i == max_realloc_count)
10651 fail("Parsing failed even at max reallocation count");
10652 }
10653
START_TEST(test_nsalloc_realloc_long_context)10654 START_TEST(test_nsalloc_realloc_long_context) {
10655 const char *text
10656 = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10657 " <!ENTITY en SYSTEM 'bar'>\n"
10658 "]>\n"
10659 "<doc xmlns='http://example.org/"
10660 /* 64 characters per line */
10661 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10662 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10663 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10664 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10665 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10666 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10667 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10668 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10669 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10670 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10671 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10672 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10673 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10674 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10675 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10676 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKL"
10677 "'>\n"
10678 "&en;"
10679 "</doc>";
10680
10681 context_realloc_test(text);
10682 }
10683 END_TEST
10684
START_TEST(test_nsalloc_realloc_long_context_2)10685 START_TEST(test_nsalloc_realloc_long_context_2) {
10686 const char *text
10687 = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10688 " <!ENTITY en SYSTEM 'bar'>\n"
10689 "]>\n"
10690 "<doc xmlns='http://example.org/"
10691 /* 64 characters per line */
10692 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10693 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10694 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10695 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10696 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10697 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10698 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10699 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10700 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10701 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10702 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10703 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10704 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10705 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10706 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10707 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJK"
10708 "'>\n"
10709 "&en;"
10710 "</doc>";
10711
10712 context_realloc_test(text);
10713 }
10714 END_TEST
10715
START_TEST(test_nsalloc_realloc_long_context_3)10716 START_TEST(test_nsalloc_realloc_long_context_3) {
10717 const char *text
10718 = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10719 " <!ENTITY en SYSTEM 'bar'>\n"
10720 "]>\n"
10721 "<doc xmlns='http://example.org/"
10722 /* 64 characters per line */
10723 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10724 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10725 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10726 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10727 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10728 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10729 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10730 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10731 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10732 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10733 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10734 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10735 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10736 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10737 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10738 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGH"
10739 "'>\n"
10740 "&en;"
10741 "</doc>";
10742
10743 context_realloc_test(text);
10744 }
10745 END_TEST
10746
START_TEST(test_nsalloc_realloc_long_context_4)10747 START_TEST(test_nsalloc_realloc_long_context_4) {
10748 const char *text
10749 = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10750 " <!ENTITY en SYSTEM 'bar'>\n"
10751 "]>\n"
10752 "<doc xmlns='http://example.org/"
10753 /* 64 characters per line */
10754 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10755 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10756 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10757 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10758 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10759 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10760 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10761 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10762 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10763 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10764 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10765 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10766 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10767 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10768 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10769 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO"
10770 "'>\n"
10771 "&en;"
10772 "</doc>";
10773
10774 context_realloc_test(text);
10775 }
10776 END_TEST
10777
START_TEST(test_nsalloc_realloc_long_context_5)10778 START_TEST(test_nsalloc_realloc_long_context_5) {
10779 const char *text
10780 = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10781 " <!ENTITY en SYSTEM 'bar'>\n"
10782 "]>\n"
10783 "<doc xmlns='http://example.org/"
10784 /* 64 characters per line */
10785 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10786 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10787 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10788 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10789 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10790 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10791 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10792 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10793 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10794 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10795 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10796 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10797 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10798 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10799 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10800 "ABC"
10801 "'>\n"
10802 "&en;"
10803 "</doc>";
10804
10805 context_realloc_test(text);
10806 }
10807 END_TEST
10808
START_TEST(test_nsalloc_realloc_long_context_6)10809 START_TEST(test_nsalloc_realloc_long_context_6) {
10810 const char *text
10811 = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10812 " <!ENTITY en SYSTEM 'bar'>\n"
10813 "]>\n"
10814 "<doc xmlns='http://example.org/"
10815 /* 64 characters per line */
10816 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10817 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10818 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10819 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10820 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10821 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10822 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10823 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10824 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10825 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10826 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10827 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10828 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10829 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10830 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
10831 "'>\n"
10832 "&en;"
10833 "</doc>";
10834
10835 context_realloc_test(text);
10836 }
10837 END_TEST
10838
START_TEST(test_nsalloc_realloc_long_context_7)10839 START_TEST(test_nsalloc_realloc_long_context_7) {
10840 const char *text
10841 = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10842 " <!ENTITY en SYSTEM 'bar'>\n"
10843 "]>\n"
10844 "<doc xmlns='http://example.org/"
10845 /* 64 characters per line */
10846 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10847 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
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/ABCDEFGHIJKLM"
10862 "'>\n"
10863 "&en;"
10864 "</doc>";
10865
10866 context_realloc_test(text);
10867 }
10868 END_TEST
10869
START_TEST(test_nsalloc_realloc_long_ge_name)10870 START_TEST(test_nsalloc_realloc_long_ge_name) {
10871 const char *text
10872 = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10873 " <!ENTITY "
10874 /* 64 characters per line */
10875 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10876 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10877 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10878 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10879 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10880 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10881 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10882 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10883 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10884 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10885 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10886 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10887 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10888 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10889 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10890 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10891 " SYSTEM 'bar'>\n"
10892 "]>\n"
10893 "<doc xmlns='http://example.org/baz'>\n"
10894 "&"
10895 /* 64 characters per line */
10896 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10897 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10898 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10899 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10900 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10901 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10902 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10903 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10904 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10905 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10906 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10907 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10908 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10909 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10910 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10911 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10912 ";"
10913 "</doc>";
10914 ExtOption options[] = {
10915 {XCS("foo"), "<!ELEMENT el EMPTY>"}, {XCS("bar"), "<el/>"}, {NULL, NULL}};
10916 int i;
10917 const int max_realloc_count = 10;
10918
10919 for (i = 0; i < max_realloc_count; i++) {
10920 reallocation_count = i;
10921 XML_SetUserData(g_parser, options);
10922 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
10923 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
10924 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10925 != XML_STATUS_ERROR)
10926 break;
10927 /* See comment in test_nsalloc_xmlns() */
10928 nsalloc_teardown();
10929 nsalloc_setup();
10930 }
10931 if (i == 0)
10932 fail("Parsing worked despite failing reallocations");
10933 else if (i == max_realloc_count)
10934 fail("Parsing failed even at max reallocation count");
10935 }
10936 END_TEST
10937
10938 /* Test that when a namespace is passed through the context mechanism
10939 * to an external entity parser, the parsers handle reallocation
10940 * failures correctly. The prefix is exactly the right length to
10941 * provoke particular uncommon code paths.
10942 */
START_TEST(test_nsalloc_realloc_long_context_in_dtd)10943 START_TEST(test_nsalloc_realloc_long_context_in_dtd) {
10944 const char *text1
10945 = "<!DOCTYPE "
10946 /* 64 characters per line */
10947 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10948 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10949 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10950 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10951 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10952 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10953 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10954 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10955 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10956 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10957 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10958 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10959 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10960 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10961 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10962 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10963 ":doc [\n"
10964 " <!ENTITY First SYSTEM 'foo/First'>\n"
10965 "]>\n"
10966 "<"
10967 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10968 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10969 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10970 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10971 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10972 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10973 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10974 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10975 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10976 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10977 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10978 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10979 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10980 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10981 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10982 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10983 ":doc xmlns:"
10984 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10985 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10986 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10987 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10988 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10989 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10990 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10991 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10992 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10993 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10994 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10995 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10996 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10997 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10998 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10999 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11000 "='foo/Second'>&First;";
11001 const char *text2
11002 = "</"
11003 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11004 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11005 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11006 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11007 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11008 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11009 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11010 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11011 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11012 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11013 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11014 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11015 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11016 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11017 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11018 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11019 ":doc>";
11020 ExtOption options[] = {{XCS("foo/First"), "Hello world"}, {NULL, NULL}};
11021 int i;
11022 const int max_realloc_count = 20;
11023
11024 for (i = 0; i < max_realloc_count; i++) {
11025 reallocation_count = i;
11026 XML_SetUserData(g_parser, options);
11027 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11028 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11029 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
11030 != XML_STATUS_ERROR
11031 && _XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2),
11032 XML_TRUE)
11033 != XML_STATUS_ERROR)
11034 break;
11035 /* See comment in test_nsalloc_xmlns() */
11036 nsalloc_teardown();
11037 nsalloc_setup();
11038 }
11039 if (i == 0)
11040 fail("Parsing worked despite failing reallocations");
11041 else if (i == max_realloc_count)
11042 fail("Parsing failed even at max reallocation count");
11043 }
11044 END_TEST
11045
START_TEST(test_nsalloc_long_default_in_ext)11046 START_TEST(test_nsalloc_long_default_in_ext) {
11047 const char *text
11048 = "<!DOCTYPE doc [\n"
11049 " <!ATTLIST e a1 CDATA '"
11050 /* 64 characters per line */
11051 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11052 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11053 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11054 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11055 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11056 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11057 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11058 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11059 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11060 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11061 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11062 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11063 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11064 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11065 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11066 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11067 "'>\n"
11068 " <!ENTITY x SYSTEM 'foo'>\n"
11069 "]>\n"
11070 "<doc>&x;</doc>";
11071 ExtOption options[] = {{XCS("foo"), "<e/>"}, {NULL, NULL}};
11072 int i;
11073 const int max_alloc_count = 50;
11074
11075 for (i = 0; i < max_alloc_count; i++) {
11076 allocation_count = i;
11077 XML_SetUserData(g_parser, options);
11078 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11079 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11080 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
11081 != XML_STATUS_ERROR)
11082 break;
11083
11084 /* See comment in test_nsalloc_xmlns() */
11085 nsalloc_teardown();
11086 nsalloc_setup();
11087 }
11088 if (i == 0)
11089 fail("Parsing worked despite failing allocations");
11090 else if (i == max_alloc_count)
11091 fail("Parsing failed even at max allocation count");
11092 }
11093 END_TEST
11094
START_TEST(test_nsalloc_long_systemid_in_ext)11095 START_TEST(test_nsalloc_long_systemid_in_ext) {
11096 const char *text
11097 = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11098 " <!ENTITY en SYSTEM '"
11099 /* 64 characters per line */
11100 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11101 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11102 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11103 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11104 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11105 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11106 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11107 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11108 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11109 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11110 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11111 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11112 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11113 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11114 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11115 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11116 "'>\n"
11117 "]>\n"
11118 "<doc>&en;</doc>";
11119 ExtOption options[] = {
11120 {XCS("foo"), "<!ELEMENT e EMPTY>"},
11121 {/* clang-format off */
11122 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11123 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11124 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11125 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11126 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11127 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11128 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11129 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11130 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11131 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11132 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11133 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11134 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11135 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11136 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11137 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"),
11138 /* clang-format on */
11139 "<e/>"},
11140 {NULL, NULL}};
11141 int i;
11142 const int max_alloc_count = 55;
11143
11144 for (i = 0; i < max_alloc_count; i++) {
11145 allocation_count = i;
11146 XML_SetUserData(g_parser, options);
11147 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11148 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11149 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
11150 != XML_STATUS_ERROR)
11151 break;
11152
11153 /* See comment in test_nsalloc_xmlns() */
11154 nsalloc_teardown();
11155 nsalloc_setup();
11156 }
11157 if (i == 0)
11158 fail("Parsing worked despite failing allocations");
11159 else if (i == max_alloc_count)
11160 fail("Parsing failed even at max allocation count");
11161 }
11162 END_TEST
11163
11164 /* Test the effects of allocation failure on parsing an element in a
11165 * namespace. Based on test_nsalloc_long_context.
11166 */
START_TEST(test_nsalloc_prefixed_element)11167 START_TEST(test_nsalloc_prefixed_element) {
11168 const char *text = "<!DOCTYPE pfx:element SYSTEM 'foo' [\n"
11169 " <!ATTLIST pfx:element baz ID #REQUIRED>\n"
11170 " <!ENTITY en SYSTEM 'bar'>\n"
11171 "]>\n"
11172 "<pfx:element xmlns:pfx='http://example.org/' baz='2'>\n"
11173 "&en;"
11174 "</pfx:element>";
11175 ExtOption options[] = {
11176 {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}};
11177 int i;
11178 const int max_alloc_count = 70;
11179
11180 for (i = 0; i < max_alloc_count; i++) {
11181 allocation_count = i;
11182 XML_SetUserData(g_parser, options);
11183 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11184 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11185 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
11186 != XML_STATUS_ERROR)
11187 break;
11188
11189 /* See comment in test_nsalloc_xmlns() */
11190 nsalloc_teardown();
11191 nsalloc_setup();
11192 }
11193 if (i == 0)
11194 fail("Success despite failing allocator");
11195 else if (i == max_alloc_count)
11196 fail("Failed even at full allocation count");
11197 }
11198 END_TEST
11199
11200 static Suite *
make_suite(void)11201 make_suite(void) {
11202 Suite *s = suite_create("basic");
11203 TCase *tc_basic = tcase_create("basic tests");
11204 TCase *tc_namespace = tcase_create("XML namespaces");
11205 TCase *tc_misc = tcase_create("miscellaneous tests");
11206 TCase *tc_alloc = tcase_create("allocation tests");
11207 TCase *tc_nsalloc = tcase_create("namespace allocation tests");
11208
11209 suite_add_tcase(s, tc_basic);
11210 tcase_add_checked_fixture(tc_basic, basic_setup, basic_teardown);
11211 tcase_add_test(tc_basic, test_nul_byte);
11212 tcase_add_test(tc_basic, test_u0000_char);
11213 tcase_add_test(tc_basic, test_siphash_self);
11214 tcase_add_test(tc_basic, test_siphash_spec);
11215 tcase_add_test(tc_basic, test_bom_utf8);
11216 tcase_add_test(tc_basic, test_bom_utf16_be);
11217 tcase_add_test(tc_basic, test_bom_utf16_le);
11218 tcase_add_test(tc_basic, test_nobom_utf16_le);
11219 tcase_add_test(tc_basic, test_illegal_utf8);
11220 tcase_add_test(tc_basic, test_utf8_auto_align);
11221 tcase_add_test(tc_basic, test_utf16);
11222 tcase_add_test(tc_basic, test_utf16_le_epilog_newline);
11223 tcase_add_test(tc_basic, test_not_utf16);
11224 tcase_add_test(tc_basic, test_bad_encoding);
11225 tcase_add_test(tc_basic, test_latin1_umlauts);
11226 tcase_add_test(tc_basic, test_long_utf8_character);
11227 tcase_add_test(tc_basic, test_long_latin1_attribute);
11228 tcase_add_test(tc_basic, test_long_ascii_attribute);
11229 /* Regression test for SF bug #491986. */
11230 tcase_add_test(tc_basic, test_danish_latin1);
11231 /* Regression test for SF bug #514281. */
11232 tcase_add_test(tc_basic, test_french_charref_hexidecimal);
11233 tcase_add_test(tc_basic, test_french_charref_decimal);
11234 tcase_add_test(tc_basic, test_french_latin1);
11235 tcase_add_test(tc_basic, test_french_utf8);
11236 tcase_add_test(tc_basic, test_utf8_false_rejection);
11237 tcase_add_test(tc_basic, test_line_number_after_parse);
11238 tcase_add_test(tc_basic, test_column_number_after_parse);
11239 tcase_add_test(tc_basic, test_line_and_column_numbers_inside_handlers);
11240 tcase_add_test(tc_basic, test_line_number_after_error);
11241 tcase_add_test(tc_basic, test_column_number_after_error);
11242 tcase_add_test(tc_basic, test_really_long_lines);
11243 tcase_add_test(tc_basic, test_really_long_encoded_lines);
11244 tcase_add_test(tc_basic, test_end_element_events);
11245 tcase_add_test(tc_basic, test_attr_whitespace_normalization);
11246 tcase_add_test(tc_basic, test_xmldecl_misplaced);
11247 tcase_add_test(tc_basic, test_xmldecl_invalid);
11248 tcase_add_test(tc_basic, test_xmldecl_missing_attr);
11249 tcase_add_test(tc_basic, test_xmldecl_missing_value);
11250 tcase_add_test(tc_basic, test_unknown_encoding_internal_entity);
11251 tcase_add_test(tc_basic, test_unrecognised_encoding_internal_entity);
11252 tcase_add_test(tc_basic, test_wfc_undeclared_entity_unread_external_subset);
11253 tcase_add_test(tc_basic, test_wfc_undeclared_entity_no_external_subset);
11254 tcase_add_test(tc_basic, test_wfc_undeclared_entity_standalone);
11255 tcase_add_test(tc_basic, test_wfc_undeclared_entity_with_external_subset);
11256 tcase_add_test(tc_basic, test_not_standalone_handler_reject);
11257 tcase_add_test(tc_basic, test_not_standalone_handler_accept);
11258 tcase_add_test(tc_basic,
11259 test_wfc_undeclared_entity_with_external_subset_standalone);
11260 tcase_add_test(tc_basic, test_entity_with_external_subset_unless_standalone);
11261 tcase_add_test(tc_basic, test_wfc_no_recursive_entity_refs);
11262 tcase_add_test(tc_basic, test_ext_entity_set_encoding);
11263 tcase_add_test(tc_basic, test_ext_entity_no_handler);
11264 tcase_add_test(tc_basic, test_ext_entity_set_bom);
11265 tcase_add_test(tc_basic, test_ext_entity_bad_encoding);
11266 tcase_add_test(tc_basic, test_ext_entity_bad_encoding_2);
11267 tcase_add_test(tc_basic, test_ext_entity_invalid_parse);
11268 tcase_add_test(tc_basic, test_ext_entity_invalid_suspended_parse);
11269 tcase_add_test(tc_basic, test_dtd_default_handling);
11270 tcase_add_test(tc_basic, test_dtd_attr_handling);
11271 tcase_add_test(tc_basic, test_empty_ns_without_namespaces);
11272 tcase_add_test(tc_basic, test_ns_in_attribute_default_without_namespaces);
11273 tcase_add_test(tc_basic, test_stop_parser_between_char_data_calls);
11274 tcase_add_test(tc_basic, test_suspend_parser_between_char_data_calls);
11275 tcase_add_test(tc_basic, test_repeated_stop_parser_between_char_data_calls);
11276 tcase_add_test(tc_basic, test_good_cdata_ascii);
11277 tcase_add_test(tc_basic, test_good_cdata_utf16);
11278 tcase_add_test(tc_basic, test_good_cdata_utf16_le);
11279 tcase_add_test(tc_basic, test_long_cdata_utf16);
11280 #ifndef XML_MIN_SIZE /* FIXME workaround -DXML_MIN_SIZE + ASan (issue #332) */
11281 tcase_add_test(tc_basic, test_multichar_cdata_utf16);
11282 #endif
11283 tcase_add_test(tc_basic, test_utf16_bad_surrogate_pair);
11284 tcase_add_test(tc_basic, test_bad_cdata);
11285 #ifndef XML_MIN_SIZE /* FIXME workaround -DXML_MIN_SIZE + ASan (issue #332) */
11286 tcase_add_test(tc_basic, test_bad_cdata_utf16);
11287 #endif
11288 tcase_add_test(tc_basic, test_stop_parser_between_cdata_calls);
11289 tcase_add_test(tc_basic, test_suspend_parser_between_cdata_calls);
11290 tcase_add_test(tc_basic, test_memory_allocation);
11291 tcase_add_test(tc_basic, test_default_current);
11292 tcase_add_test(tc_basic, test_dtd_elements);
11293 tcase_add_test(tc_basic, test_set_foreign_dtd);
11294 tcase_add_test(tc_basic, test_foreign_dtd_not_standalone);
11295 tcase_add_test(tc_basic, test_invalid_foreign_dtd);
11296 tcase_add_test(tc_basic, test_foreign_dtd_with_doctype);
11297 tcase_add_test(tc_basic, test_foreign_dtd_without_external_subset);
11298 tcase_add_test(tc_basic, test_empty_foreign_dtd);
11299 tcase_add_test(tc_basic, test_set_base);
11300 tcase_add_test(tc_basic, test_attributes);
11301 tcase_add_test(tc_basic, test_reset_in_entity);
11302 tcase_add_test(tc_basic, test_resume_invalid_parse);
11303 tcase_add_test(tc_basic, test_resume_resuspended);
11304 tcase_add_test(tc_basic, test_cdata_default);
11305 tcase_add_test(tc_basic, test_subordinate_reset);
11306 tcase_add_test(tc_basic, test_subordinate_suspend);
11307 tcase_add_test(tc_basic, test_subordinate_xdecl_suspend);
11308 tcase_add_test(tc_basic, test_subordinate_xdecl_abort);
11309 tcase_add_test(tc_basic, test_explicit_encoding);
11310 tcase_add_test(tc_basic, test_trailing_cr);
11311 tcase_add_test(tc_basic, test_ext_entity_trailing_cr);
11312 tcase_add_test(tc_basic, test_trailing_rsqb);
11313 tcase_add_test(tc_basic, test_ext_entity_trailing_rsqb);
11314 tcase_add_test(tc_basic, test_ext_entity_good_cdata);
11315 tcase_add_test(tc_basic, test_user_parameters);
11316 tcase_add_test(tc_basic, test_ext_entity_ref_parameter);
11317 tcase_add_test(tc_basic, test_empty_parse);
11318 tcase_add_test(tc_basic, test_get_buffer_1);
11319 tcase_add_test(tc_basic, test_get_buffer_2);
11320 tcase_add_test(tc_basic, test_byte_info_at_end);
11321 tcase_add_test(tc_basic, test_byte_info_at_error);
11322 tcase_add_test(tc_basic, test_byte_info_at_cdata);
11323 tcase_add_test(tc_basic, test_predefined_entities);
11324 tcase_add_test(tc_basic, test_invalid_tag_in_dtd);
11325 tcase_add_test(tc_basic, test_not_predefined_entities);
11326 tcase_add_test(tc_basic, test_ignore_section);
11327 tcase_add_test(tc_basic, test_ignore_section_utf16);
11328 tcase_add_test(tc_basic, test_ignore_section_utf16_be);
11329 tcase_add_test(tc_basic, test_bad_ignore_section);
11330 tcase_add_test(tc_basic, test_external_entity_values);
11331 tcase_add_test(tc_basic, test_ext_entity_not_standalone);
11332 tcase_add_test(tc_basic, test_ext_entity_value_abort);
11333 tcase_add_test(tc_basic, test_bad_public_doctype);
11334 tcase_add_test(tc_basic, test_attribute_enum_value);
11335 tcase_add_test(tc_basic, test_predefined_entity_redefinition);
11336 tcase_add_test(tc_basic, test_dtd_stop_processing);
11337 tcase_add_test(tc_basic, test_public_notation_no_sysid);
11338 tcase_add_test(tc_basic, test_nested_groups);
11339 tcase_add_test(tc_basic, test_group_choice);
11340 tcase_add_test(tc_basic, test_standalone_parameter_entity);
11341 tcase_add_test(tc_basic, test_skipped_parameter_entity);
11342 tcase_add_test(tc_basic, test_recursive_external_parameter_entity);
11343 tcase_add_test(tc_basic, test_undefined_ext_entity_in_external_dtd);
11344 tcase_add_test(tc_basic, test_suspend_xdecl);
11345 tcase_add_test(tc_basic, test_abort_epilog);
11346 tcase_add_test(tc_basic, test_abort_epilog_2);
11347 tcase_add_test(tc_basic, test_suspend_epilog);
11348 tcase_add_test(tc_basic, test_suspend_in_sole_empty_tag);
11349 tcase_add_test(tc_basic, test_unfinished_epilog);
11350 tcase_add_test(tc_basic, test_partial_char_in_epilog);
11351 tcase_add_test(tc_basic, test_hash_collision);
11352 tcase_add_test(tc_basic, test_suspend_resume_internal_entity);
11353 tcase_add_test(tc_basic, test_resume_entity_with_syntax_error);
11354 tcase_add_test(tc_basic, test_suspend_resume_parameter_entity);
11355 tcase_add_test(tc_basic, test_restart_on_error);
11356 tcase_add_test(tc_basic, test_reject_lt_in_attribute_value);
11357 tcase_add_test(tc_basic, test_reject_unfinished_param_in_att_value);
11358 tcase_add_test(tc_basic, test_trailing_cr_in_att_value);
11359 tcase_add_test(tc_basic, test_standalone_internal_entity);
11360 tcase_add_test(tc_basic, test_skipped_external_entity);
11361 tcase_add_test(tc_basic, test_skipped_null_loaded_ext_entity);
11362 tcase_add_test(tc_basic, test_skipped_unloaded_ext_entity);
11363 tcase_add_test(tc_basic, test_param_entity_with_trailing_cr);
11364 tcase_add_test(tc_basic, test_invalid_character_entity);
11365 tcase_add_test(tc_basic, test_invalid_character_entity_2);
11366 tcase_add_test(tc_basic, test_invalid_character_entity_3);
11367 tcase_add_test(tc_basic, test_invalid_character_entity_4);
11368 tcase_add_test(tc_basic, test_pi_handled_in_default);
11369 tcase_add_test(tc_basic, test_comment_handled_in_default);
11370 tcase_add_test(tc_basic, test_pi_yml);
11371 tcase_add_test(tc_basic, test_pi_xnl);
11372 tcase_add_test(tc_basic, test_pi_xmm);
11373 tcase_add_test(tc_basic, test_utf16_pi);
11374 tcase_add_test(tc_basic, test_utf16_be_pi);
11375 tcase_add_test(tc_basic, test_utf16_be_comment);
11376 tcase_add_test(tc_basic, test_utf16_le_comment);
11377 tcase_add_test(tc_basic, test_missing_encoding_conversion_fn);
11378 tcase_add_test(tc_basic, test_failing_encoding_conversion_fn);
11379 tcase_add_test(tc_basic, test_unknown_encoding_success);
11380 tcase_add_test(tc_basic, test_unknown_encoding_bad_name);
11381 tcase_add_test(tc_basic, test_unknown_encoding_bad_name_2);
11382 tcase_add_test(tc_basic, test_unknown_encoding_long_name_1);
11383 tcase_add_test(tc_basic, test_unknown_encoding_long_name_2);
11384 tcase_add_test(tc_basic, test_invalid_unknown_encoding);
11385 tcase_add_test(tc_basic, test_unknown_ascii_encoding_ok);
11386 tcase_add_test(tc_basic, test_unknown_ascii_encoding_fail);
11387 tcase_add_test(tc_basic, test_unknown_encoding_invalid_length);
11388 tcase_add_test(tc_basic, test_unknown_encoding_invalid_topbit);
11389 tcase_add_test(tc_basic, test_unknown_encoding_invalid_surrogate);
11390 tcase_add_test(tc_basic, test_unknown_encoding_invalid_high);
11391 tcase_add_test(tc_basic, test_unknown_encoding_invalid_attr_value);
11392 tcase_add_test(tc_basic, test_ext_entity_latin1_utf16le_bom);
11393 tcase_add_test(tc_basic, test_ext_entity_latin1_utf16be_bom);
11394 tcase_add_test(tc_basic, test_ext_entity_latin1_utf16le_bom2);
11395 tcase_add_test(tc_basic, test_ext_entity_latin1_utf16be_bom2);
11396 tcase_add_test(tc_basic, test_ext_entity_utf16_be);
11397 tcase_add_test(tc_basic, test_ext_entity_utf16_le);
11398 tcase_add_test(tc_basic, test_ext_entity_utf16_unknown);
11399 tcase_add_test(tc_basic, test_ext_entity_utf8_non_bom);
11400 tcase_add_test(tc_basic, test_utf8_in_cdata_section);
11401 tcase_add_test(tc_basic, test_utf8_in_cdata_section_2);
11402 tcase_add_test(tc_basic, test_trailing_spaces_in_elements);
11403 tcase_add_test(tc_basic, test_utf16_attribute);
11404 tcase_add_test(tc_basic, test_utf16_second_attr);
11405 tcase_add_test(tc_basic, test_attr_after_solidus);
11406 tcase_add_test(tc_basic, test_utf16_pe);
11407 tcase_add_test(tc_basic, test_bad_attr_desc_keyword);
11408 tcase_add_test(tc_basic, test_bad_attr_desc_keyword_utf16);
11409 tcase_add_test(tc_basic, test_bad_doctype);
11410 tcase_add_test(tc_basic, test_bad_doctype_utf16);
11411 tcase_add_test(tc_basic, test_bad_doctype_plus);
11412 tcase_add_test(tc_basic, test_bad_doctype_star);
11413 tcase_add_test(tc_basic, test_bad_doctype_query);
11414 tcase_add_test(tc_basic, test_unknown_encoding_bad_ignore);
11415 tcase_add_test(tc_basic, test_entity_in_utf16_be_attr);
11416 tcase_add_test(tc_basic, test_entity_in_utf16_le_attr);
11417 tcase_add_test(tc_basic, test_entity_public_utf16_be);
11418 tcase_add_test(tc_basic, test_entity_public_utf16_le);
11419 tcase_add_test(tc_basic, test_short_doctype);
11420 tcase_add_test(tc_basic, test_short_doctype_2);
11421 tcase_add_test(tc_basic, test_short_doctype_3);
11422 tcase_add_test(tc_basic, test_long_doctype);
11423 tcase_add_test(tc_basic, test_bad_entity);
11424 tcase_add_test(tc_basic, test_bad_entity_2);
11425 tcase_add_test(tc_basic, test_bad_entity_3);
11426 tcase_add_test(tc_basic, test_bad_entity_4);
11427 tcase_add_test(tc_basic, test_bad_notation);
11428 tcase_add_test(tc_basic, test_default_doctype_handler);
11429 tcase_add_test(tc_basic, test_empty_element_abort);
11430
11431 suite_add_tcase(s, tc_namespace);
11432 tcase_add_checked_fixture(tc_namespace, namespace_setup, namespace_teardown);
11433 tcase_add_test(tc_namespace, test_return_ns_triplet);
11434 tcase_add_test(tc_namespace, test_ns_tagname_overwrite);
11435 tcase_add_test(tc_namespace, test_ns_tagname_overwrite_triplet);
11436 tcase_add_test(tc_namespace, test_start_ns_clears_start_element);
11437 tcase_add_test(tc_namespace, test_default_ns_from_ext_subset_and_ext_ge);
11438 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_1);
11439 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_2);
11440 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_3);
11441 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_4);
11442 tcase_add_test(tc_namespace, test_ns_unbound_prefix);
11443 tcase_add_test(tc_namespace, test_ns_default_with_empty_uri);
11444 tcase_add_test(tc_namespace, test_ns_duplicate_attrs_diff_prefixes);
11445 tcase_add_test(tc_namespace, test_ns_duplicate_hashes);
11446 tcase_add_test(tc_namespace, test_ns_unbound_prefix_on_attribute);
11447 tcase_add_test(tc_namespace, test_ns_unbound_prefix_on_element);
11448 tcase_add_test(tc_namespace, test_ns_parser_reset);
11449 tcase_add_test(tc_namespace, test_ns_long_element);
11450 tcase_add_test(tc_namespace, test_ns_mixed_prefix_atts);
11451 tcase_add_test(tc_namespace, test_ns_extend_uri_buffer);
11452 tcase_add_test(tc_namespace, test_ns_reserved_attributes);
11453 tcase_add_test(tc_namespace, test_ns_reserved_attributes_2);
11454 tcase_add_test(tc_namespace, test_ns_extremely_long_prefix);
11455 tcase_add_test(tc_namespace, test_ns_unknown_encoding_success);
11456 tcase_add_test(tc_namespace, test_ns_double_colon);
11457 tcase_add_test(tc_namespace, test_ns_double_colon_element);
11458 tcase_add_test(tc_namespace, test_ns_bad_attr_leafname);
11459 tcase_add_test(tc_namespace, test_ns_bad_element_leafname);
11460 tcase_add_test(tc_namespace, test_ns_utf16_leafname);
11461 tcase_add_test(tc_namespace, test_ns_utf16_element_leafname);
11462 tcase_add_test(tc_namespace, test_ns_utf16_doctype);
11463 tcase_add_test(tc_namespace, test_ns_invalid_doctype);
11464 tcase_add_test(tc_namespace, test_ns_double_colon_doctype);
11465
11466 suite_add_tcase(s, tc_misc);
11467 tcase_add_checked_fixture(tc_misc, NULL, basic_teardown);
11468 tcase_add_test(tc_misc, test_misc_alloc_create_parser);
11469 tcase_add_test(tc_misc, test_misc_alloc_create_parser_with_encoding);
11470 tcase_add_test(tc_misc, test_misc_null_parser);
11471 tcase_add_test(tc_misc, test_misc_error_string);
11472 tcase_add_test(tc_misc, test_misc_version);
11473 tcase_add_test(tc_misc, test_misc_features);
11474 tcase_add_test(tc_misc, test_misc_attribute_leak);
11475 tcase_add_test(tc_misc, test_misc_utf16le);
11476 tcase_add_test(tc_misc, test_misc_stop_during_end_handler_issue_240_1);
11477 tcase_add_test(tc_misc, test_misc_stop_during_end_handler_issue_240_2);
11478 #ifdef XML_DTD
11479 tcase_add_test(tc_misc,
11480 test_misc_deny_internal_entity_closing_doctype_issue_317);
11481 #endif
11482
11483 suite_add_tcase(s, tc_alloc);
11484 tcase_add_checked_fixture(tc_alloc, alloc_setup, alloc_teardown);
11485 tcase_add_test(tc_alloc, test_alloc_parse_xdecl);
11486 tcase_add_test(tc_alloc, test_alloc_parse_xdecl_2);
11487 tcase_add_test(tc_alloc, test_alloc_parse_pi);
11488 tcase_add_test(tc_alloc, test_alloc_parse_pi_2);
11489 tcase_add_test(tc_alloc, test_alloc_parse_pi_3);
11490 tcase_add_test(tc_alloc, test_alloc_parse_comment);
11491 tcase_add_test(tc_alloc, test_alloc_parse_comment_2);
11492 tcase_add_test(tc_alloc, test_alloc_create_external_parser);
11493 tcase_add_test(tc_alloc, test_alloc_run_external_parser);
11494 tcase_add_test(tc_alloc, test_alloc_dtd_copy_default_atts);
11495 tcase_add_test(tc_alloc, test_alloc_external_entity);
11496 tcase_add_test(tc_alloc, test_alloc_ext_entity_set_encoding);
11497 tcase_add_test(tc_alloc, test_alloc_internal_entity);
11498 tcase_add_test(tc_alloc, test_alloc_dtd_default_handling);
11499 tcase_add_test(tc_alloc, test_alloc_explicit_encoding);
11500 tcase_add_test(tc_alloc, test_alloc_set_base);
11501 tcase_add_test(tc_alloc, test_alloc_realloc_buffer);
11502 tcase_add_test(tc_alloc, test_alloc_ext_entity_realloc_buffer);
11503 tcase_add_test(tc_alloc, test_alloc_realloc_many_attributes);
11504 tcase_add_test(tc_alloc, test_alloc_public_entity_value);
11505 tcase_add_test(tc_alloc, test_alloc_realloc_subst_public_entity_value);
11506 tcase_add_test(tc_alloc, test_alloc_parse_public_doctype);
11507 tcase_add_test(tc_alloc, test_alloc_parse_public_doctype_long_name);
11508 tcase_add_test(tc_alloc, test_alloc_set_foreign_dtd);
11509 tcase_add_test(tc_alloc, test_alloc_attribute_enum_value);
11510 tcase_add_test(tc_alloc, test_alloc_realloc_attribute_enum_value);
11511 tcase_add_test(tc_alloc, test_alloc_realloc_implied_attribute);
11512 tcase_add_test(tc_alloc, test_alloc_realloc_default_attribute);
11513 tcase_add_test(tc_alloc, test_alloc_notation);
11514 tcase_add_test(tc_alloc, test_alloc_public_notation);
11515 tcase_add_test(tc_alloc, test_alloc_system_notation);
11516 tcase_add_test(tc_alloc, test_alloc_nested_groups);
11517 tcase_add_test(tc_alloc, test_alloc_realloc_nested_groups);
11518 tcase_add_test(tc_alloc, test_alloc_large_group);
11519 tcase_add_test(tc_alloc, test_alloc_realloc_group_choice);
11520 tcase_add_test(tc_alloc, test_alloc_pi_in_epilog);
11521 tcase_add_test(tc_alloc, test_alloc_comment_in_epilog);
11522 tcase_add_test(tc_alloc, test_alloc_realloc_long_attribute_value);
11523 tcase_add_test(tc_alloc, test_alloc_attribute_whitespace);
11524 tcase_add_test(tc_alloc, test_alloc_attribute_predefined_entity);
11525 tcase_add_test(tc_alloc, test_alloc_long_attr_default_with_char_ref);
11526 tcase_add_test(tc_alloc, test_alloc_long_attr_value);
11527 tcase_add_test(tc_alloc, test_alloc_nested_entities);
11528 tcase_add_test(tc_alloc, test_alloc_realloc_param_entity_newline);
11529 tcase_add_test(tc_alloc, test_alloc_realloc_ce_extends_pe);
11530 tcase_add_test(tc_alloc, test_alloc_realloc_attributes);
11531 tcase_add_test(tc_alloc, test_alloc_long_doc_name);
11532 tcase_add_test(tc_alloc, test_alloc_long_base);
11533 tcase_add_test(tc_alloc, test_alloc_long_public_id);
11534 tcase_add_test(tc_alloc, test_alloc_long_entity_value);
11535 tcase_add_test(tc_alloc, test_alloc_long_notation);
11536
11537 suite_add_tcase(s, tc_nsalloc);
11538 tcase_add_checked_fixture(tc_nsalloc, nsalloc_setup, nsalloc_teardown);
11539 tcase_add_test(tc_nsalloc, test_nsalloc_xmlns);
11540 tcase_add_test(tc_nsalloc, test_nsalloc_parse_buffer);
11541 tcase_add_test(tc_nsalloc, test_nsalloc_long_prefix);
11542 tcase_add_test(tc_nsalloc, test_nsalloc_long_uri);
11543 tcase_add_test(tc_nsalloc, test_nsalloc_long_attr);
11544 tcase_add_test(tc_nsalloc, test_nsalloc_long_attr_prefix);
11545 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_attributes);
11546 tcase_add_test(tc_nsalloc, test_nsalloc_long_element);
11547 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_binding_uri);
11548 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_prefix);
11549 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_longer_prefix);
11550 tcase_add_test(tc_nsalloc, test_nsalloc_long_namespace);
11551 tcase_add_test(tc_nsalloc, test_nsalloc_less_long_namespace);
11552 tcase_add_test(tc_nsalloc, test_nsalloc_long_context);
11553 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context);
11554 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_2);
11555 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_3);
11556 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_4);
11557 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_5);
11558 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_6);
11559 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_7);
11560 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_ge_name);
11561 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_in_dtd);
11562 tcase_add_test(tc_nsalloc, test_nsalloc_long_default_in_ext);
11563 tcase_add_test(tc_nsalloc, test_nsalloc_long_systemid_in_ext);
11564 tcase_add_test(tc_nsalloc, test_nsalloc_prefixed_element);
11565
11566 return s;
11567 }
11568
11569 int
main(int argc,char * argv[])11570 main(int argc, char *argv[]) {
11571 int i, nf;
11572 int verbosity = CK_NORMAL;
11573 Suite *s = make_suite();
11574 SRunner *sr = srunner_create(s);
11575
11576 /* run the tests for internal helper functions */
11577 testhelper_is_whitespace_normalized();
11578
11579 for (i = 1; i < argc; ++i) {
11580 char *opt = argv[i];
11581 if (strcmp(opt, "-v") == 0 || strcmp(opt, "--verbose") == 0)
11582 verbosity = CK_VERBOSE;
11583 else if (strcmp(opt, "-q") == 0 || strcmp(opt, "--quiet") == 0)
11584 verbosity = CK_SILENT;
11585 else {
11586 fprintf(stderr, "runtests: unknown option '%s'\n", opt);
11587 return 2;
11588 }
11589 }
11590 if (verbosity != CK_SILENT)
11591 printf("Expat version: %" XML_FMT_STR "\n", XML_ExpatVersion());
11592 srunner_run_all(sr, verbosity);
11593 nf = srunner_ntests_failed(sr);
11594 srunner_free(sr);
11595
11596 return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
11597 }
11598