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 #include <stdint.h> /* intptr_t uint64_t */
49
50 #if ! defined(__cplusplus)
51 # include <stdbool.h>
52 #endif
53
54 #include "expat.h"
55 #include "chardata.h"
56 #include "structdata.h"
57 #include "internal.h" /* for UNUSED_P only */
58 #include "minicheck.h"
59 #include "memcheck.h"
60 #include "siphash.h"
61 #include "ascii.h" /* for ASCII_xxx */
62
63 #ifdef XML_LARGE_SIZE
64 # define XML_FMT_INT_MOD "ll"
65 #else
66 # define XML_FMT_INT_MOD "l"
67 #endif
68
69 #ifdef XML_UNICODE_WCHAR_T
70 # define XML_FMT_CHAR "lc"
71 # define XML_FMT_STR "ls"
72 # include <wchar.h>
73 # define xcstrlen(s) wcslen(s)
74 # define xcstrcmp(s, t) wcscmp((s), (t))
75 # define xcstrncmp(s, t, n) wcsncmp((s), (t), (n))
76 # define XCS(s) _XCS(s)
77 # define _XCS(s) L##s
78 #else
79 # ifdef XML_UNICODE
80 # error "No support for UTF-16 character without wchar_t in tests"
81 # else
82 # define XML_FMT_CHAR "c"
83 # define XML_FMT_STR "s"
84 # define xcstrlen(s) strlen(s)
85 # define xcstrcmp(s, t) strcmp((s), (t))
86 # define xcstrncmp(s, t, n) strncmp((s), (t), (n))
87 # define XCS(s) s
88 # endif /* XML_UNICODE */
89 #endif /* XML_UNICODE_WCHAR_T */
90
91 static XML_Parser g_parser = NULL;
92
93 static void
tcase_add_test__ifdef_xml_dtd(TCase * tc,tcase_test_function test)94 tcase_add_test__ifdef_xml_dtd(TCase *tc, tcase_test_function test) {
95 #ifdef XML_DTD
96 tcase_add_test(tc, test);
97 #else
98 UNUSED_P(tc);
99 UNUSED_P(test);
100 #endif
101 }
102
103 static void
basic_setup(void)104 basic_setup(void) {
105 g_parser = XML_ParserCreate(NULL);
106 if (g_parser == NULL)
107 fail("Parser not created.");
108 }
109
110 static void
basic_teardown(void)111 basic_teardown(void) {
112 if (g_parser != NULL) {
113 XML_ParserFree(g_parser);
114 g_parser = NULL;
115 }
116 }
117
118 /* Generate a failure using the parser state to create an error message;
119 this should be used when the parser reports an error we weren't
120 expecting.
121 */
122 static void
_xml_failure(XML_Parser parser,const char * file,int line)123 _xml_failure(XML_Parser parser, const char *file, int line) {
124 char buffer[1024];
125 enum XML_Error err = XML_GetErrorCode(parser);
126 sprintf(buffer,
127 " %d: %" XML_FMT_STR " (line %" XML_FMT_INT_MOD
128 "u, offset %" XML_FMT_INT_MOD "u)\n reported from %s, line %d\n",
129 err, XML_ErrorString(err), XML_GetCurrentLineNumber(parser),
130 XML_GetCurrentColumnNumber(parser), file, line);
131 _fail_unless(0, file, line, buffer);
132 }
133
134 static enum XML_Status
_XML_Parse_SINGLE_BYTES(XML_Parser parser,const char * s,int len,int isFinal)135 _XML_Parse_SINGLE_BYTES(XML_Parser parser, const char *s, int len,
136 int isFinal) {
137 enum XML_Status res = XML_STATUS_ERROR;
138 int offset = 0;
139
140 if (len == 0) {
141 return XML_Parse(parser, s, len, isFinal);
142 }
143
144 for (; offset < len; offset++) {
145 const int innerIsFinal = (offset == len - 1) && isFinal;
146 const char c = s[offset]; /* to help out-of-bounds detection */
147 res = XML_Parse(parser, &c, sizeof(char), innerIsFinal);
148 if (res != XML_STATUS_OK) {
149 return res;
150 }
151 }
152 return res;
153 }
154
155 #define xml_failure(parser) _xml_failure((parser), __FILE__, __LINE__)
156
157 static void
_expect_failure(const char * text,enum XML_Error errorCode,const char * errorMessage,const char * file,int lineno)158 _expect_failure(const char *text, enum XML_Error errorCode,
159 const char *errorMessage, const char *file, int lineno) {
160 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
161 == XML_STATUS_OK)
162 /* Hackish use of _fail_unless() macro, but let's us report
163 the right filename and line number. */
164 _fail_unless(0, file, lineno, errorMessage);
165 if (XML_GetErrorCode(g_parser) != errorCode)
166 _xml_failure(g_parser, file, lineno);
167 }
168
169 #define expect_failure(text, errorCode, errorMessage) \
170 _expect_failure((text), (errorCode), (errorMessage), __FILE__, __LINE__)
171
172 /* Dummy handlers for when we need to set a handler to tickle a bug,
173 but it doesn't need to do anything.
174 */
175 static unsigned long dummy_handler_flags = 0;
176
177 #define DUMMY_START_DOCTYPE_HANDLER_FLAG (1UL << 0)
178 #define DUMMY_END_DOCTYPE_HANDLER_FLAG (1UL << 1)
179 #define DUMMY_ENTITY_DECL_HANDLER_FLAG (1UL << 2)
180 #define DUMMY_NOTATION_DECL_HANDLER_FLAG (1UL << 3)
181 #define DUMMY_ELEMENT_DECL_HANDLER_FLAG (1UL << 4)
182 #define DUMMY_ATTLIST_DECL_HANDLER_FLAG (1UL << 5)
183 #define DUMMY_COMMENT_HANDLER_FLAG (1UL << 6)
184 #define DUMMY_PI_HANDLER_FLAG (1UL << 7)
185 #define DUMMY_START_ELEMENT_HANDLER_FLAG (1UL << 8)
186 #define DUMMY_START_CDATA_HANDLER_FLAG (1UL << 9)
187 #define DUMMY_END_CDATA_HANDLER_FLAG (1UL << 10)
188 #define DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG (1UL << 11)
189 #define DUMMY_START_NS_DECL_HANDLER_FLAG (1UL << 12)
190 #define DUMMY_END_NS_DECL_HANDLER_FLAG (1UL << 13)
191 #define DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG (1UL << 14)
192 #define DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG (1UL << 15)
193 #define DUMMY_SKIP_HANDLER_FLAG (1UL << 16)
194 #define DUMMY_DEFAULT_HANDLER_FLAG (1UL << 17)
195
196 static void XMLCALL
dummy_xdecl_handler(void * userData,const XML_Char * version,const XML_Char * encoding,int standalone)197 dummy_xdecl_handler(void *userData, const XML_Char *version,
198 const XML_Char *encoding, int standalone) {
199 UNUSED_P(userData);
200 UNUSED_P(version);
201 UNUSED_P(encoding);
202 UNUSED_P(standalone);
203 }
204
205 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)206 dummy_start_doctype_handler(void *userData, const XML_Char *doctypeName,
207 const XML_Char *sysid, const XML_Char *pubid,
208 int has_internal_subset) {
209 UNUSED_P(userData);
210 UNUSED_P(doctypeName);
211 UNUSED_P(sysid);
212 UNUSED_P(pubid);
213 UNUSED_P(has_internal_subset);
214 dummy_handler_flags |= DUMMY_START_DOCTYPE_HANDLER_FLAG;
215 }
216
217 static void XMLCALL
dummy_end_doctype_handler(void * userData)218 dummy_end_doctype_handler(void *userData) {
219 UNUSED_P(userData);
220 dummy_handler_flags |= DUMMY_END_DOCTYPE_HANDLER_FLAG;
221 }
222
223 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)224 dummy_entity_decl_handler(void *userData, const XML_Char *entityName,
225 int is_parameter_entity, const XML_Char *value,
226 int value_length, const XML_Char *base,
227 const XML_Char *systemId, const XML_Char *publicId,
228 const XML_Char *notationName) {
229 UNUSED_P(userData);
230 UNUSED_P(entityName);
231 UNUSED_P(is_parameter_entity);
232 UNUSED_P(value);
233 UNUSED_P(value_length);
234 UNUSED_P(base);
235 UNUSED_P(systemId);
236 UNUSED_P(publicId);
237 UNUSED_P(notationName);
238 dummy_handler_flags |= DUMMY_ENTITY_DECL_HANDLER_FLAG;
239 }
240
241 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)242 dummy_notation_decl_handler(void *userData, const XML_Char *notationName,
243 const XML_Char *base, const XML_Char *systemId,
244 const XML_Char *publicId) {
245 UNUSED_P(userData);
246 UNUSED_P(notationName);
247 UNUSED_P(base);
248 UNUSED_P(systemId);
249 UNUSED_P(publicId);
250 dummy_handler_flags |= DUMMY_NOTATION_DECL_HANDLER_FLAG;
251 }
252
253 static void XMLCALL
dummy_element_decl_handler(void * userData,const XML_Char * name,XML_Content * model)254 dummy_element_decl_handler(void *userData, const XML_Char *name,
255 XML_Content *model) {
256 UNUSED_P(userData);
257 UNUSED_P(name);
258 /* The content model must be freed by the handler. Unfortunately
259 * we cannot pass the parser as the userData because this is used
260 * with other handlers that require other userData.
261 */
262 XML_FreeContentModel(g_parser, model);
263 dummy_handler_flags |= DUMMY_ELEMENT_DECL_HANDLER_FLAG;
264 }
265
266 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)267 dummy_attlist_decl_handler(void *userData, const XML_Char *elname,
268 const XML_Char *attname, const XML_Char *att_type,
269 const XML_Char *dflt, int isrequired) {
270 UNUSED_P(userData);
271 UNUSED_P(elname);
272 UNUSED_P(attname);
273 UNUSED_P(att_type);
274 UNUSED_P(dflt);
275 UNUSED_P(isrequired);
276 dummy_handler_flags |= DUMMY_ATTLIST_DECL_HANDLER_FLAG;
277 }
278
279 static void XMLCALL
dummy_comment_handler(void * userData,const XML_Char * data)280 dummy_comment_handler(void *userData, const XML_Char *data) {
281 UNUSED_P(userData);
282 UNUSED_P(data);
283 dummy_handler_flags |= DUMMY_COMMENT_HANDLER_FLAG;
284 }
285
286 static void XMLCALL
dummy_pi_handler(void * userData,const XML_Char * target,const XML_Char * data)287 dummy_pi_handler(void *userData, const XML_Char *target, const XML_Char *data) {
288 UNUSED_P(userData);
289 UNUSED_P(target);
290 UNUSED_P(data);
291 dummy_handler_flags |= DUMMY_PI_HANDLER_FLAG;
292 }
293
294 static void XMLCALL
dummy_start_element(void * userData,const XML_Char * name,const XML_Char ** atts)295 dummy_start_element(void *userData, const XML_Char *name,
296 const XML_Char **atts) {
297 UNUSED_P(userData);
298 UNUSED_P(name);
299 UNUSED_P(atts);
300 dummy_handler_flags |= DUMMY_START_ELEMENT_HANDLER_FLAG;
301 }
302
303 static void XMLCALL
dummy_end_element(void * userData,const XML_Char * name)304 dummy_end_element(void *userData, const XML_Char *name) {
305 UNUSED_P(userData);
306 UNUSED_P(name);
307 }
308
309 static void XMLCALL
dummy_start_cdata_handler(void * userData)310 dummy_start_cdata_handler(void *userData) {
311 UNUSED_P(userData);
312 dummy_handler_flags |= DUMMY_START_CDATA_HANDLER_FLAG;
313 }
314
315 static void XMLCALL
dummy_end_cdata_handler(void * userData)316 dummy_end_cdata_handler(void *userData) {
317 UNUSED_P(userData);
318 dummy_handler_flags |= DUMMY_END_CDATA_HANDLER_FLAG;
319 }
320
321 static void XMLCALL
dummy_cdata_handler(void * userData,const XML_Char * s,int len)322 dummy_cdata_handler(void *userData, const XML_Char *s, int len) {
323 UNUSED_P(userData);
324 UNUSED_P(s);
325 UNUSED_P(len);
326 }
327
328 static void XMLCALL
dummy_start_namespace_decl_handler(void * userData,const XML_Char * prefix,const XML_Char * uri)329 dummy_start_namespace_decl_handler(void *userData, const XML_Char *prefix,
330 const XML_Char *uri) {
331 UNUSED_P(userData);
332 UNUSED_P(prefix);
333 UNUSED_P(uri);
334 dummy_handler_flags |= DUMMY_START_NS_DECL_HANDLER_FLAG;
335 }
336
337 static void XMLCALL
dummy_end_namespace_decl_handler(void * userData,const XML_Char * prefix)338 dummy_end_namespace_decl_handler(void *userData, const XML_Char *prefix) {
339 UNUSED_P(userData);
340 UNUSED_P(prefix);
341 dummy_handler_flags |= DUMMY_END_NS_DECL_HANDLER_FLAG;
342 }
343
344 /* This handler is obsolete, but while the code exists we should
345 * ensure that dealing with the handler is covered by tests.
346 */
347 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)348 dummy_unparsed_entity_decl_handler(void *userData, const XML_Char *entityName,
349 const XML_Char *base,
350 const XML_Char *systemId,
351 const XML_Char *publicId,
352 const XML_Char *notationName) {
353 UNUSED_P(userData);
354 UNUSED_P(entityName);
355 UNUSED_P(base);
356 UNUSED_P(systemId);
357 UNUSED_P(publicId);
358 UNUSED_P(notationName);
359 dummy_handler_flags |= DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG;
360 }
361
362 static void XMLCALL
dummy_default_handler(void * userData,const XML_Char * s,int len)363 dummy_default_handler(void *userData, const XML_Char *s, int len) {
364 UNUSED_P(userData);
365 UNUSED_P(s);
366 UNUSED_P(len);
367 }
368
369 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)370 dummy_start_doctype_decl_handler(void *userData, const XML_Char *doctypeName,
371 const XML_Char *sysid, const XML_Char *pubid,
372 int has_internal_subset) {
373 UNUSED_P(userData);
374 UNUSED_P(doctypeName);
375 UNUSED_P(sysid);
376 UNUSED_P(pubid);
377 UNUSED_P(has_internal_subset);
378 dummy_handler_flags |= DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG;
379 }
380
381 static void XMLCALL
dummy_end_doctype_decl_handler(void * userData)382 dummy_end_doctype_decl_handler(void *userData) {
383 UNUSED_P(userData);
384 dummy_handler_flags |= DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG;
385 }
386
387 static void XMLCALL
dummy_skip_handler(void * userData,const XML_Char * entityName,int is_parameter_entity)388 dummy_skip_handler(void *userData, const XML_Char *entityName,
389 int is_parameter_entity) {
390 UNUSED_P(userData);
391 UNUSED_P(entityName);
392 UNUSED_P(is_parameter_entity);
393 dummy_handler_flags |= DUMMY_SKIP_HANDLER_FLAG;
394 }
395
396 /* Useful external entity handler */
397 typedef struct ExtOption {
398 const XML_Char *system_id;
399 const char *parse_text;
400 } ExtOption;
401
402 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)403 external_entity_optioner(XML_Parser parser, const XML_Char *context,
404 const XML_Char *base, const XML_Char *systemId,
405 const XML_Char *publicId) {
406 ExtOption *options = (ExtOption *)XML_GetUserData(parser);
407 XML_Parser ext_parser;
408
409 UNUSED_P(base);
410 UNUSED_P(publicId);
411 while (options->parse_text != NULL) {
412 if (! xcstrcmp(systemId, options->system_id)) {
413 enum XML_Status rc;
414 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
415 if (ext_parser == NULL)
416 return XML_STATUS_ERROR;
417 rc = _XML_Parse_SINGLE_BYTES(ext_parser, options->parse_text,
418 (int)strlen(options->parse_text), XML_TRUE);
419 XML_ParserFree(ext_parser);
420 return rc;
421 }
422 options++;
423 }
424 fail("No suitable option found");
425 return XML_STATUS_ERROR;
426 }
427
428 /*
429 * Parameter entity evaluation support.
430 */
431 #define ENTITY_MATCH_FAIL (-1)
432 #define ENTITY_MATCH_NOT_FOUND (0)
433 #define ENTITY_MATCH_SUCCESS (1)
434 static const XML_Char *entity_name_to_match = NULL;
435 static const XML_Char *entity_value_to_match = NULL;
436 static int entity_match_flag = ENTITY_MATCH_NOT_FOUND;
437
438 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)439 param_entity_match_handler(void *userData, const XML_Char *entityName,
440 int is_parameter_entity, const XML_Char *value,
441 int value_length, const XML_Char *base,
442 const XML_Char *systemId, const XML_Char *publicId,
443 const XML_Char *notationName) {
444 UNUSED_P(userData);
445 UNUSED_P(base);
446 UNUSED_P(systemId);
447 UNUSED_P(publicId);
448 UNUSED_P(notationName);
449 if (! is_parameter_entity || entity_name_to_match == NULL
450 || entity_value_to_match == NULL) {
451 return;
452 }
453 if (! xcstrcmp(entityName, entity_name_to_match)) {
454 /* The cast here is safe because we control the horizontal and
455 * the vertical, and we therefore know our strings are never
456 * going to overflow an int.
457 */
458 if (value_length != (int)xcstrlen(entity_value_to_match)
459 || xcstrncmp(value, entity_value_to_match, value_length)) {
460 entity_match_flag = ENTITY_MATCH_FAIL;
461 } else {
462 entity_match_flag = ENTITY_MATCH_SUCCESS;
463 }
464 }
465 /* Else leave the match flag alone */
466 }
467
468 /*
469 * Character & encoding tests.
470 */
471
START_TEST(test_nul_byte)472 START_TEST(test_nul_byte) {
473 char text[] = "<doc>\0</doc>";
474
475 /* test that a NUL byte (in US-ASCII data) is an error */
476 if (_XML_Parse_SINGLE_BYTES(g_parser, text, sizeof(text) - 1, XML_TRUE)
477 == XML_STATUS_OK)
478 fail("Parser did not report error on NUL-byte.");
479 if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
480 xml_failure(g_parser);
481 }
482 END_TEST
483
START_TEST(test_u0000_char)484 START_TEST(test_u0000_char) {
485 /* test that a NUL byte (in US-ASCII data) is an error */
486 expect_failure("<doc>�</doc>", XML_ERROR_BAD_CHAR_REF,
487 "Parser did not report error on NUL-byte.");
488 }
489 END_TEST
490
START_TEST(test_siphash_self)491 START_TEST(test_siphash_self) {
492 if (! sip24_valid())
493 fail("SipHash self-test failed");
494 }
495 END_TEST
496
START_TEST(test_siphash_spec)497 START_TEST(test_siphash_spec) {
498 /* https://131002.net/siphash/siphash.pdf (page 19, "Test values") */
499 const char message[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09"
500 "\x0a\x0b\x0c\x0d\x0e";
501 const size_t len = sizeof(message) - 1;
502 const uint64_t expected = _SIP_ULL(0xa129ca61U, 0x49be45e5U);
503 struct siphash state;
504 struct sipkey key;
505
506 sip_tokey(&key, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09"
507 "\x0a\x0b\x0c\x0d\x0e\x0f");
508 sip24_init(&state, &key);
509
510 /* Cover spread across calls */
511 sip24_update(&state, message, 4);
512 sip24_update(&state, message + 4, len - 4);
513
514 /* Cover null length */
515 sip24_update(&state, message, 0);
516
517 if (sip24_final(&state) != expected)
518 fail("sip24_final failed spec test\n");
519
520 /* Cover wrapper */
521 if (siphash24(message, len, &key) != expected)
522 fail("siphash24 failed spec test\n");
523 }
524 END_TEST
525
START_TEST(test_bom_utf8)526 START_TEST(test_bom_utf8) {
527 /* This test is really just making sure we don't core on a UTF-8 BOM. */
528 const char *text = "\357\273\277<e/>";
529
530 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
531 == XML_STATUS_ERROR)
532 xml_failure(g_parser);
533 }
534 END_TEST
535
START_TEST(test_bom_utf16_be)536 START_TEST(test_bom_utf16_be) {
537 char text[] = "\376\377\0<\0e\0/\0>";
538
539 if (_XML_Parse_SINGLE_BYTES(g_parser, text, sizeof(text) - 1, XML_TRUE)
540 == XML_STATUS_ERROR)
541 xml_failure(g_parser);
542 }
543 END_TEST
544
START_TEST(test_bom_utf16_le)545 START_TEST(test_bom_utf16_le) {
546 char text[] = "\377\376<\0e\0/\0>\0";
547
548 if (_XML_Parse_SINGLE_BYTES(g_parser, text, sizeof(text) - 1, XML_TRUE)
549 == XML_STATUS_ERROR)
550 xml_failure(g_parser);
551 }
552 END_TEST
553
554 /* Parse whole buffer at once to exercise a different code path */
START_TEST(test_nobom_utf16_le)555 START_TEST(test_nobom_utf16_le) {
556 char text[] = " \0<\0e\0/\0>\0";
557
558 if (XML_Parse(g_parser, text, sizeof(text) - 1, XML_TRUE) == XML_STATUS_ERROR)
559 xml_failure(g_parser);
560 }
561 END_TEST
562
563 static void XMLCALL
accumulate_characters(void * userData,const XML_Char * s,int len)564 accumulate_characters(void *userData, const XML_Char *s, int len) {
565 CharData_AppendXMLChars((CharData *)userData, s, len);
566 }
567
568 static void XMLCALL
accumulate_attribute(void * userData,const XML_Char * name,const XML_Char ** atts)569 accumulate_attribute(void *userData, const XML_Char *name,
570 const XML_Char **atts) {
571 CharData *storage = (CharData *)userData;
572 UNUSED_P(name);
573 /* Check there are attributes to deal with */
574 if (atts == NULL)
575 return;
576
577 while (storage->count < 0 && atts[0] != NULL) {
578 /* "accumulate" the value of the first attribute we see */
579 CharData_AppendXMLChars(storage, atts[1], -1);
580 atts += 2;
581 }
582 }
583
584 static void
_run_character_check(const char * text,const XML_Char * expected,const char * file,int line)585 _run_character_check(const char *text, const XML_Char *expected,
586 const char *file, int line) {
587 CharData storage;
588
589 CharData_Init(&storage);
590 XML_SetUserData(g_parser, &storage);
591 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
592 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
593 == XML_STATUS_ERROR)
594 _xml_failure(g_parser, file, line);
595 CharData_CheckXMLChars(&storage, expected);
596 }
597
598 #define run_character_check(text, expected) \
599 _run_character_check(text, expected, __FILE__, __LINE__)
600
601 static void
_run_attribute_check(const char * text,const XML_Char * expected,const char * file,int line)602 _run_attribute_check(const char *text, const XML_Char *expected,
603 const char *file, int line) {
604 CharData storage;
605
606 CharData_Init(&storage);
607 XML_SetUserData(g_parser, &storage);
608 XML_SetStartElementHandler(g_parser, accumulate_attribute);
609 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
610 == XML_STATUS_ERROR)
611 _xml_failure(g_parser, file, line);
612 CharData_CheckXMLChars(&storage, expected);
613 }
614
615 #define run_attribute_check(text, expected) \
616 _run_attribute_check(text, expected, __FILE__, __LINE__)
617
618 typedef struct ExtTest {
619 const char *parse_text;
620 const XML_Char *encoding;
621 CharData *storage;
622 } ExtTest;
623
624 static void XMLCALL
ext_accumulate_characters(void * userData,const XML_Char * s,int len)625 ext_accumulate_characters(void *userData, const XML_Char *s, int len) {
626 ExtTest *test_data = (ExtTest *)userData;
627 accumulate_characters(test_data->storage, s, len);
628 }
629
630 static void
_run_ext_character_check(const char * text,ExtTest * test_data,const XML_Char * expected,const char * file,int line)631 _run_ext_character_check(const char *text, ExtTest *test_data,
632 const XML_Char *expected, const char *file, int line) {
633 CharData *const storage = (CharData *)malloc(sizeof(CharData));
634
635 CharData_Init(storage);
636 test_data->storage = storage;
637 XML_SetUserData(g_parser, test_data);
638 XML_SetCharacterDataHandler(g_parser, ext_accumulate_characters);
639 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
640 == XML_STATUS_ERROR)
641 _xml_failure(g_parser, file, line);
642 CharData_CheckXMLChars(storage, expected);
643
644 free(storage);
645 }
646
647 #define run_ext_character_check(text, test_data, expected) \
648 _run_ext_character_check(text, test_data, expected, __FILE__, __LINE__)
649
650 /* Regression test for SF bug #491986. */
START_TEST(test_danish_latin1)651 START_TEST(test_danish_latin1) {
652 const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
653 "<e>J\xF8rgen \xE6\xF8\xE5\xC6\xD8\xC5</e>";
654 #ifdef XML_UNICODE
655 const XML_Char *expected
656 = XCS("J\x00f8rgen \x00e6\x00f8\x00e5\x00c6\x00d8\x00c5");
657 #else
658 const XML_Char *expected
659 = XCS("J\xC3\xB8rgen \xC3\xA6\xC3\xB8\xC3\xA5\xC3\x86\xC3\x98\xC3\x85");
660 #endif
661 run_character_check(text, expected);
662 }
663 END_TEST
664
665 /* Regression test for SF bug #514281. */
START_TEST(test_french_charref_hexidecimal)666 START_TEST(test_french_charref_hexidecimal) {
667 const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
668 "<doc>éèàçêÈ</doc>";
669 #ifdef XML_UNICODE
670 const XML_Char *expected = XCS("\x00e9\x00e8\x00e0\x00e7\x00ea\x00c8");
671 #else
672 const XML_Char *expected
673 = XCS("\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88");
674 #endif
675 run_character_check(text, expected);
676 }
677 END_TEST
678
START_TEST(test_french_charref_decimal)679 START_TEST(test_french_charref_decimal) {
680 const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
681 "<doc>éèàçêÈ</doc>";
682 #ifdef XML_UNICODE
683 const XML_Char *expected = XCS("\x00e9\x00e8\x00e0\x00e7\x00ea\x00c8");
684 #else
685 const XML_Char *expected
686 = XCS("\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88");
687 #endif
688 run_character_check(text, expected);
689 }
690 END_TEST
691
START_TEST(test_french_latin1)692 START_TEST(test_french_latin1) {
693 const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
694 "<doc>\xE9\xE8\xE0\xE7\xEa\xC8</doc>";
695 #ifdef XML_UNICODE
696 const XML_Char *expected = XCS("\x00e9\x00e8\x00e0\x00e7\x00ea\x00c8");
697 #else
698 const XML_Char *expected
699 = XCS("\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88");
700 #endif
701 run_character_check(text, expected);
702 }
703 END_TEST
704
START_TEST(test_french_utf8)705 START_TEST(test_french_utf8) {
706 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
707 "<doc>\xC3\xA9</doc>";
708 #ifdef XML_UNICODE
709 const XML_Char *expected = XCS("\x00e9");
710 #else
711 const XML_Char *expected = XCS("\xC3\xA9");
712 #endif
713 run_character_check(text, expected);
714 }
715 END_TEST
716
717 /* Regression test for SF bug #600479.
718 XXX There should be a test that exercises all legal XML Unicode
719 characters as PCDATA and attribute value content, and XML Name
720 characters as part of element and attribute names.
721 */
START_TEST(test_utf8_false_rejection)722 START_TEST(test_utf8_false_rejection) {
723 const char *text = "<doc>\xEF\xBA\xBF</doc>";
724 #ifdef XML_UNICODE
725 const XML_Char *expected = XCS("\xfebf");
726 #else
727 const XML_Char *expected = XCS("\xEF\xBA\xBF");
728 #endif
729 run_character_check(text, expected);
730 }
731 END_TEST
732
733 /* Regression test for SF bug #477667.
734 This test assures that any 8-bit character followed by a 7-bit
735 character will not be mistakenly interpreted as a valid UTF-8
736 sequence.
737 */
START_TEST(test_illegal_utf8)738 START_TEST(test_illegal_utf8) {
739 char text[100];
740 int i;
741
742 for (i = 128; i <= 255; ++i) {
743 sprintf(text, "<e>%ccd</e>", i);
744 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
745 == XML_STATUS_OK) {
746 sprintf(text, "expected token error for '%c' (ordinal %d) in UTF-8 text",
747 i, i);
748 fail(text);
749 } else if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
750 xml_failure(g_parser);
751 /* Reset the parser since we use the same parser repeatedly. */
752 XML_ParserReset(g_parser, NULL);
753 }
754 }
755 END_TEST
756
757 /* Examples, not masks: */
758 #define UTF8_LEAD_1 "\x7f" /* 0b01111111 */
759 #define UTF8_LEAD_2 "\xdf" /* 0b11011111 */
760 #define UTF8_LEAD_3 "\xef" /* 0b11101111 */
761 #define UTF8_LEAD_4 "\xf7" /* 0b11110111 */
762 #define UTF8_FOLLOW "\xbf" /* 0b10111111 */
763
START_TEST(test_utf8_auto_align)764 START_TEST(test_utf8_auto_align) {
765 struct TestCase {
766 ptrdiff_t expectedMovementInChars;
767 const char *input;
768 };
769
770 struct TestCase cases[] = {
771 {00, ""},
772
773 {00, UTF8_LEAD_1},
774
775 {-1, UTF8_LEAD_2},
776 {00, UTF8_LEAD_2 UTF8_FOLLOW},
777
778 {-1, UTF8_LEAD_3},
779 {-2, UTF8_LEAD_3 UTF8_FOLLOW},
780 {00, UTF8_LEAD_3 UTF8_FOLLOW UTF8_FOLLOW},
781
782 {-1, UTF8_LEAD_4},
783 {-2, UTF8_LEAD_4 UTF8_FOLLOW},
784 {-3, UTF8_LEAD_4 UTF8_FOLLOW UTF8_FOLLOW},
785 {00, UTF8_LEAD_4 UTF8_FOLLOW UTF8_FOLLOW UTF8_FOLLOW},
786 };
787
788 size_t i = 0;
789 bool success = true;
790 for (; i < sizeof(cases) / sizeof(*cases); i++) {
791 const char *fromLim = cases[i].input + strlen(cases[i].input);
792 const char *const fromLimInitially = fromLim;
793 ptrdiff_t actualMovementInChars;
794
795 _INTERNAL_trim_to_complete_utf8_characters(cases[i].input, &fromLim);
796
797 actualMovementInChars = (fromLim - fromLimInitially);
798 if (actualMovementInChars != cases[i].expectedMovementInChars) {
799 size_t j = 0;
800 success = false;
801 printf("[-] UTF-8 case %2u: Expected movement by %2d chars"
802 ", actually moved by %2d chars: \"",
803 (unsigned)(i + 1), (int)cases[i].expectedMovementInChars,
804 (int)actualMovementInChars);
805 for (; j < strlen(cases[i].input); j++) {
806 printf("\\x%02x", (unsigned char)cases[i].input[j]);
807 }
808 printf("\"\n");
809 }
810 }
811
812 if (! success) {
813 fail("UTF-8 auto-alignment is not bullet-proof\n");
814 }
815 }
816 END_TEST
817
START_TEST(test_utf16)818 START_TEST(test_utf16) {
819 /* <?xml version="1.0" encoding="UTF-16"?>
820 * <doc a='123'>some {A} text</doc>
821 *
822 * where {A} is U+FF21, FULLWIDTH LATIN CAPITAL LETTER A
823 */
824 char text[]
825 = "\000<\000?\000x\000m\000\154\000 \000v\000e\000r\000s\000i\000o"
826 "\000n\000=\000'\0001\000.\000\060\000'\000 \000e\000n\000c\000o"
827 "\000d\000i\000n\000g\000=\000'\000U\000T\000F\000-\0001\000\066"
828 "\000'\000?\000>\000\n"
829 "\000<\000d\000o\000c\000 \000a\000=\000'\0001\0002\0003\000'\000>"
830 "\000s\000o\000m\000e\000 \xff\x21\000 \000t\000e\000x\000t\000"
831 "<\000/\000d\000o\000c\000>";
832 #ifdef XML_UNICODE
833 const XML_Char *expected = XCS("some \xff21 text");
834 #else
835 const XML_Char *expected = XCS("some \357\274\241 text");
836 #endif
837 CharData storage;
838
839 CharData_Init(&storage);
840 XML_SetUserData(g_parser, &storage);
841 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
842 if (_XML_Parse_SINGLE_BYTES(g_parser, text, sizeof(text) - 1, XML_TRUE)
843 == XML_STATUS_ERROR)
844 xml_failure(g_parser);
845 CharData_CheckXMLChars(&storage, expected);
846 }
847 END_TEST
848
START_TEST(test_utf16_le_epilog_newline)849 START_TEST(test_utf16_le_epilog_newline) {
850 unsigned int first_chunk_bytes = 17;
851 char text[] = "\xFF\xFE" /* BOM */
852 "<\000e\000/\000>\000" /* document element */
853 "\r\000\n\000\r\000\n\000"; /* epilog */
854
855 if (first_chunk_bytes >= sizeof(text) - 1)
856 fail("bad value of first_chunk_bytes");
857 if (_XML_Parse_SINGLE_BYTES(g_parser, text, first_chunk_bytes, XML_FALSE)
858 == XML_STATUS_ERROR)
859 xml_failure(g_parser);
860 else {
861 enum XML_Status rc;
862 rc = _XML_Parse_SINGLE_BYTES(g_parser, text + first_chunk_bytes,
863 sizeof(text) - first_chunk_bytes - 1,
864 XML_TRUE);
865 if (rc == XML_STATUS_ERROR)
866 xml_failure(g_parser);
867 }
868 }
869 END_TEST
870
871 /* Test that an outright lie in the encoding is faulted */
START_TEST(test_not_utf16)872 START_TEST(test_not_utf16) {
873 const char *text = "<?xml version='1.0' encoding='utf-16'?>"
874 "<doc>Hi</doc>";
875
876 /* Use a handler to provoke the appropriate code paths */
877 XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler);
878 expect_failure(text, XML_ERROR_INCORRECT_ENCODING,
879 "UTF-16 declared in UTF-8 not faulted");
880 }
881 END_TEST
882
883 /* Test that an unknown encoding is rejected */
START_TEST(test_bad_encoding)884 START_TEST(test_bad_encoding) {
885 const char *text = "<doc>Hi</doc>";
886
887 if (! XML_SetEncoding(g_parser, XCS("unknown-encoding")))
888 fail("XML_SetEncoding failed");
889 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
890 "Unknown encoding not faulted");
891 }
892 END_TEST
893
894 /* Regression test for SF bug #481609, #774028. */
START_TEST(test_latin1_umlauts)895 START_TEST(test_latin1_umlauts) {
896 const char *text
897 = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
898 "<e a='\xE4 \xF6 \xFC ä ö ü ä ö ü >'\n"
899 " >\xE4 \xF6 \xFC ä ö ü ä ö ü ></e>";
900 #ifdef XML_UNICODE
901 /* Expected results in UTF-16 */
902 const XML_Char *expected = XCS("\x00e4 \x00f6 \x00fc ")
903 XCS("\x00e4 \x00f6 \x00fc ") XCS("\x00e4 \x00f6 \x00fc >");
904 #else
905 /* Expected results in UTF-8 */
906 const XML_Char *expected = XCS("\xC3\xA4 \xC3\xB6 \xC3\xBC ")
907 XCS("\xC3\xA4 \xC3\xB6 \xC3\xBC ") XCS("\xC3\xA4 \xC3\xB6 \xC3\xBC >");
908 #endif
909
910 run_character_check(text, expected);
911 XML_ParserReset(g_parser, NULL);
912 run_attribute_check(text, expected);
913 /* Repeat with a default handler */
914 XML_ParserReset(g_parser, NULL);
915 XML_SetDefaultHandler(g_parser, dummy_default_handler);
916 run_character_check(text, expected);
917 XML_ParserReset(g_parser, NULL);
918 XML_SetDefaultHandler(g_parser, dummy_default_handler);
919 run_attribute_check(text, expected);
920 }
921 END_TEST
922
923 /* Test that an element name with a 4-byte UTF-8 character is rejected */
START_TEST(test_long_utf8_character)924 START_TEST(test_long_utf8_character) {
925 const char *text
926 = "<?xml version='1.0' encoding='utf-8'?>\n"
927 /* 0xf0 0x90 0x80 0x80 = U+10000, the first Linear B character */
928 "<do\xf0\x90\x80\x80/>";
929 expect_failure(text, XML_ERROR_INVALID_TOKEN,
930 "4-byte UTF-8 character in element name not faulted");
931 }
932 END_TEST
933
934 /* Test that a long latin-1 attribute (too long to convert in one go)
935 * is correctly converted
936 */
START_TEST(test_long_latin1_attribute)937 START_TEST(test_long_latin1_attribute) {
938 const char *text
939 = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
940 "<doc att='"
941 /* 64 characters per line */
942 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
943 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
944 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
945 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
946 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
947 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
948 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
949 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
950 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
951 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
952 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
953 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
954 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
955 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
956 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
957 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
958 /* Last character splits across a buffer boundary */
959 "\xe4'>\n</doc>";
960
961 const XML_Char *expected =
962 /* 64 characters per line */
963 /* clang-format off */
964 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
965 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
966 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
967 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
968 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
969 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
970 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
971 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
972 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
973 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
974 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
975 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
976 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
977 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
978 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
979 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO")
980 /* clang-format on */
981 #ifdef XML_UNICODE
982 XCS("\x00e4");
983 #else
984 XCS("\xc3\xa4");
985 #endif
986
987 run_attribute_check(text, expected);
988 }
989 END_TEST
990
991 /* Test that a long ASCII attribute (too long to convert in one go)
992 * is correctly converted
993 */
START_TEST(test_long_ascii_attribute)994 START_TEST(test_long_ascii_attribute) {
995 const char *text
996 = "<?xml version='1.0' encoding='us-ascii'?>\n"
997 "<doc att='"
998 /* 64 characters per line */
999 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1000 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1001 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1002 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1003 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1004 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1005 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1006 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1007 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1008 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1009 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1010 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1011 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1012 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1013 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1014 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1015 "01234'>\n</doc>";
1016 const XML_Char *expected =
1017 /* 64 characters per line */
1018 /* clang-format off */
1019 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1020 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1021 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1022 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1023 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1024 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1025 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1026 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1027 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1028 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1029 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1030 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1031 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1032 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1033 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1034 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1035 XCS("01234");
1036 /* clang-format on */
1037
1038 run_attribute_check(text, expected);
1039 }
1040 END_TEST
1041
1042 /* Regression test #1 for SF bug #653180. */
START_TEST(test_line_number_after_parse)1043 START_TEST(test_line_number_after_parse) {
1044 const char *text = "<tag>\n"
1045 "\n"
1046 "\n</tag>";
1047 XML_Size lineno;
1048
1049 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
1050 == XML_STATUS_ERROR)
1051 xml_failure(g_parser);
1052 lineno = XML_GetCurrentLineNumber(g_parser);
1053 if (lineno != 4) {
1054 char buffer[100];
1055 sprintf(buffer, "expected 4 lines, saw %" XML_FMT_INT_MOD "u", lineno);
1056 fail(buffer);
1057 }
1058 }
1059 END_TEST
1060
1061 /* Regression test #2 for SF bug #653180. */
START_TEST(test_column_number_after_parse)1062 START_TEST(test_column_number_after_parse) {
1063 const char *text = "<tag></tag>";
1064 XML_Size colno;
1065
1066 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
1067 == XML_STATUS_ERROR)
1068 xml_failure(g_parser);
1069 colno = XML_GetCurrentColumnNumber(g_parser);
1070 if (colno != 11) {
1071 char buffer[100];
1072 sprintf(buffer, "expected 11 columns, saw %" XML_FMT_INT_MOD "u", colno);
1073 fail(buffer);
1074 }
1075 }
1076 END_TEST
1077
1078 #define STRUCT_START_TAG 0
1079 #define STRUCT_END_TAG 1
1080 static void XMLCALL
start_element_event_handler2(void * userData,const XML_Char * name,const XML_Char ** attr)1081 start_element_event_handler2(void *userData, const XML_Char *name,
1082 const XML_Char **attr) {
1083 StructData *storage = (StructData *)userData;
1084 UNUSED_P(attr);
1085 StructData_AddItem(storage, name, XML_GetCurrentColumnNumber(g_parser),
1086 XML_GetCurrentLineNumber(g_parser), STRUCT_START_TAG);
1087 }
1088
1089 static void XMLCALL
end_element_event_handler2(void * userData,const XML_Char * name)1090 end_element_event_handler2(void *userData, const XML_Char *name) {
1091 StructData *storage = (StructData *)userData;
1092 StructData_AddItem(storage, name, XML_GetCurrentColumnNumber(g_parser),
1093 XML_GetCurrentLineNumber(g_parser), STRUCT_END_TAG);
1094 }
1095
1096 /* Regression test #3 for SF bug #653180. */
START_TEST(test_line_and_column_numbers_inside_handlers)1097 START_TEST(test_line_and_column_numbers_inside_handlers) {
1098 const char *text = "<a>\n" /* Unix end-of-line */
1099 " <b>\r\n" /* Windows end-of-line */
1100 " <c/>\r" /* Mac OS end-of-line */
1101 " </b>\n"
1102 " <d>\n"
1103 " <f/>\n"
1104 " </d>\n"
1105 "</a>";
1106 const StructDataEntry expected[]
1107 = {{XCS("a"), 0, 1, STRUCT_START_TAG}, {XCS("b"), 2, 2, STRUCT_START_TAG},
1108 {XCS("c"), 4, 3, STRUCT_START_TAG}, {XCS("c"), 8, 3, STRUCT_END_TAG},
1109 {XCS("b"), 2, 4, STRUCT_END_TAG}, {XCS("d"), 2, 5, STRUCT_START_TAG},
1110 {XCS("f"), 4, 6, STRUCT_START_TAG}, {XCS("f"), 8, 6, STRUCT_END_TAG},
1111 {XCS("d"), 2, 7, STRUCT_END_TAG}, {XCS("a"), 0, 8, STRUCT_END_TAG}};
1112 const int expected_count = sizeof(expected) / sizeof(StructDataEntry);
1113 StructData storage;
1114
1115 StructData_Init(&storage);
1116 XML_SetUserData(g_parser, &storage);
1117 XML_SetStartElementHandler(g_parser, start_element_event_handler2);
1118 XML_SetEndElementHandler(g_parser, end_element_event_handler2);
1119 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1120 == XML_STATUS_ERROR)
1121 xml_failure(g_parser);
1122
1123 StructData_CheckItems(&storage, expected, expected_count);
1124 StructData_Dispose(&storage);
1125 }
1126 END_TEST
1127
1128 /* Regression test #4 for SF bug #653180. */
START_TEST(test_line_number_after_error)1129 START_TEST(test_line_number_after_error) {
1130 const char *text = "<a>\n"
1131 " <b>\n"
1132 " </a>"; /* missing </b> */
1133 XML_Size lineno;
1134 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
1135 != XML_STATUS_ERROR)
1136 fail("Expected a parse error");
1137
1138 lineno = XML_GetCurrentLineNumber(g_parser);
1139 if (lineno != 3) {
1140 char buffer[100];
1141 sprintf(buffer, "expected 3 lines, saw %" XML_FMT_INT_MOD "u", lineno);
1142 fail(buffer);
1143 }
1144 }
1145 END_TEST
1146
1147 /* Regression test #5 for SF bug #653180. */
START_TEST(test_column_number_after_error)1148 START_TEST(test_column_number_after_error) {
1149 const char *text = "<a>\n"
1150 " <b>\n"
1151 " </a>"; /* missing </b> */
1152 XML_Size colno;
1153 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
1154 != XML_STATUS_ERROR)
1155 fail("Expected a parse error");
1156
1157 colno = XML_GetCurrentColumnNumber(g_parser);
1158 if (colno != 4) {
1159 char buffer[100];
1160 sprintf(buffer, "expected 4 columns, saw %" XML_FMT_INT_MOD "u", colno);
1161 fail(buffer);
1162 }
1163 }
1164 END_TEST
1165
1166 /* Regression test for SF bug #478332. */
START_TEST(test_really_long_lines)1167 START_TEST(test_really_long_lines) {
1168 /* This parses an input line longer than INIT_DATA_BUF_SIZE
1169 characters long (defined to be 1024 in xmlparse.c). We take a
1170 really cheesy approach to building the input buffer, because
1171 this avoids writing bugs in buffer-filling code.
1172 */
1173 const char *text
1174 = "<e>"
1175 /* 64 chars */
1176 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1177 /* until we have at least 1024 characters on the line: */
1178 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1179 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1180 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1181 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1182 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1183 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1184 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1185 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1186 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1187 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1188 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1189 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1190 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1191 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1192 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1193 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1194 "</e>";
1195 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1196 == XML_STATUS_ERROR)
1197 xml_failure(g_parser);
1198 }
1199 END_TEST
1200
1201 /* Test cdata processing across a buffer boundary */
START_TEST(test_really_long_encoded_lines)1202 START_TEST(test_really_long_encoded_lines) {
1203 /* As above, except that we want to provoke an output buffer
1204 * overflow with a non-trivial encoding. For this we need to pass
1205 * the whole cdata in one go, not byte-by-byte.
1206 */
1207 void *buffer;
1208 const char *text
1209 = "<?xml version='1.0' encoding='iso-8859-1'?>"
1210 "<e>"
1211 /* 64 chars */
1212 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1213 /* until we have at least 1024 characters on the line: */
1214 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1215 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1216 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1217 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1218 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1219 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1220 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1221 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1222 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1223 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1224 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1225 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1226 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1227 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1228 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1229 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1230 "</e>";
1231 int parse_len = (int)strlen(text);
1232
1233 /* Need a cdata handler to provoke the code path we want to test */
1234 XML_SetCharacterDataHandler(g_parser, dummy_cdata_handler);
1235 buffer = XML_GetBuffer(g_parser, parse_len);
1236 if (buffer == NULL)
1237 fail("Could not allocate parse buffer");
1238 assert(buffer != NULL);
1239 memcpy(buffer, text, parse_len);
1240 if (XML_ParseBuffer(g_parser, parse_len, XML_TRUE) == XML_STATUS_ERROR)
1241 xml_failure(g_parser);
1242 }
1243 END_TEST
1244
1245 /*
1246 * Element event tests.
1247 */
1248
1249 static void XMLCALL
start_element_event_handler(void * userData,const XML_Char * name,const XML_Char ** atts)1250 start_element_event_handler(void *userData, const XML_Char *name,
1251 const XML_Char **atts) {
1252 UNUSED_P(atts);
1253 CharData_AppendXMLChars((CharData *)userData, name, -1);
1254 }
1255
1256 static void XMLCALL
end_element_event_handler(void * userData,const XML_Char * name)1257 end_element_event_handler(void *userData, const XML_Char *name) {
1258 CharData *storage = (CharData *)userData;
1259 CharData_AppendXMLChars(storage, XCS("/"), 1);
1260 CharData_AppendXMLChars(storage, name, -1);
1261 }
1262
START_TEST(test_end_element_events)1263 START_TEST(test_end_element_events) {
1264 const char *text = "<a><b><c/></b><d><f/></d></a>";
1265 const XML_Char *expected = XCS("/c/b/f/d/a");
1266 CharData storage;
1267
1268 CharData_Init(&storage);
1269 XML_SetUserData(g_parser, &storage);
1270 XML_SetEndElementHandler(g_parser, end_element_event_handler);
1271 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1272 == XML_STATUS_ERROR)
1273 xml_failure(g_parser);
1274 CharData_CheckXMLChars(&storage, expected);
1275 }
1276 END_TEST
1277
1278 /*
1279 * Attribute tests.
1280 */
1281
1282 /* Helpers used by the following test; this checks any "attr" and "refs"
1283 attributes to make sure whitespace has been normalized.
1284
1285 Return true if whitespace has been normalized in a string, using
1286 the rules for attribute value normalization. The 'is_cdata' flag
1287 is needed since CDATA attributes don't need to have multiple
1288 whitespace characters collapsed to a single space, while other
1289 attribute data types do. (Section 3.3.3 of the recommendation.)
1290 */
1291 static int
is_whitespace_normalized(const XML_Char * s,int is_cdata)1292 is_whitespace_normalized(const XML_Char *s, int is_cdata) {
1293 int blanks = 0;
1294 int at_start = 1;
1295 while (*s) {
1296 if (*s == XCS(' '))
1297 ++blanks;
1298 else if (*s == XCS('\t') || *s == XCS('\n') || *s == XCS('\r'))
1299 return 0;
1300 else {
1301 if (at_start) {
1302 at_start = 0;
1303 if (blanks && ! is_cdata)
1304 /* illegal leading blanks */
1305 return 0;
1306 } else if (blanks > 1 && ! is_cdata)
1307 return 0;
1308 blanks = 0;
1309 }
1310 ++s;
1311 }
1312 if (blanks && ! is_cdata)
1313 return 0;
1314 return 1;
1315 }
1316
1317 /* Check the attribute whitespace checker: */
1318 static void
testhelper_is_whitespace_normalized(void)1319 testhelper_is_whitespace_normalized(void) {
1320 assert(is_whitespace_normalized(XCS("abc"), 0));
1321 assert(is_whitespace_normalized(XCS("abc"), 1));
1322 assert(is_whitespace_normalized(XCS("abc def ghi"), 0));
1323 assert(is_whitespace_normalized(XCS("abc def ghi"), 1));
1324 assert(! is_whitespace_normalized(XCS(" abc def ghi"), 0));
1325 assert(is_whitespace_normalized(XCS(" abc def ghi"), 1));
1326 assert(! is_whitespace_normalized(XCS("abc def ghi"), 0));
1327 assert(is_whitespace_normalized(XCS("abc def ghi"), 1));
1328 assert(! is_whitespace_normalized(XCS("abc def ghi "), 0));
1329 assert(is_whitespace_normalized(XCS("abc def ghi "), 1));
1330 assert(! is_whitespace_normalized(XCS(" "), 0));
1331 assert(is_whitespace_normalized(XCS(" "), 1));
1332 assert(! is_whitespace_normalized(XCS("\t"), 0));
1333 assert(! is_whitespace_normalized(XCS("\t"), 1));
1334 assert(! is_whitespace_normalized(XCS("\n"), 0));
1335 assert(! is_whitespace_normalized(XCS("\n"), 1));
1336 assert(! is_whitespace_normalized(XCS("\r"), 0));
1337 assert(! is_whitespace_normalized(XCS("\r"), 1));
1338 assert(! is_whitespace_normalized(XCS("abc\t def"), 1));
1339 }
1340
1341 static void XMLCALL
check_attr_contains_normalized_whitespace(void * userData,const XML_Char * name,const XML_Char ** atts)1342 check_attr_contains_normalized_whitespace(void *userData, const XML_Char *name,
1343 const XML_Char **atts) {
1344 int i;
1345 UNUSED_P(userData);
1346 UNUSED_P(name);
1347 for (i = 0; atts[i] != NULL; i += 2) {
1348 const XML_Char *attrname = atts[i];
1349 const XML_Char *value = atts[i + 1];
1350 if (xcstrcmp(XCS("attr"), attrname) == 0
1351 || xcstrcmp(XCS("ents"), attrname) == 0
1352 || xcstrcmp(XCS("refs"), attrname) == 0) {
1353 if (! is_whitespace_normalized(value, 0)) {
1354 char buffer[256];
1355 sprintf(buffer,
1356 "attribute value not normalized: %" XML_FMT_STR
1357 "='%" XML_FMT_STR "'",
1358 attrname, value);
1359 fail(buffer);
1360 }
1361 }
1362 }
1363 }
1364
START_TEST(test_attr_whitespace_normalization)1365 START_TEST(test_attr_whitespace_normalization) {
1366 const char *text
1367 = "<!DOCTYPE doc [\n"
1368 " <!ATTLIST doc\n"
1369 " attr NMTOKENS #REQUIRED\n"
1370 " ents ENTITIES #REQUIRED\n"
1371 " refs IDREFS #REQUIRED>\n"
1372 "]>\n"
1373 "<doc attr=' a b c\t\td\te\t' refs=' id-1 \t id-2\t\t' \n"
1374 " ents=' ent-1 \t\r\n"
1375 " ent-2 ' >\n"
1376 " <e id='id-1'/>\n"
1377 " <e id='id-2'/>\n"
1378 "</doc>";
1379
1380 XML_SetStartElementHandler(g_parser,
1381 check_attr_contains_normalized_whitespace);
1382 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1383 == XML_STATUS_ERROR)
1384 xml_failure(g_parser);
1385 }
1386 END_TEST
1387
1388 /*
1389 * XML declaration tests.
1390 */
1391
START_TEST(test_xmldecl_misplaced)1392 START_TEST(test_xmldecl_misplaced) {
1393 expect_failure("\n"
1394 "<?xml version='1.0'?>\n"
1395 "<a/>",
1396 XML_ERROR_MISPLACED_XML_PI,
1397 "failed to report misplaced XML declaration");
1398 }
1399 END_TEST
1400
START_TEST(test_xmldecl_invalid)1401 START_TEST(test_xmldecl_invalid) {
1402 expect_failure("<?xml version='1.0' \xc3\xa7?>\n<doc/>", XML_ERROR_XML_DECL,
1403 "Failed to report invalid XML declaration");
1404 }
1405 END_TEST
1406
START_TEST(test_xmldecl_missing_attr)1407 START_TEST(test_xmldecl_missing_attr) {
1408 expect_failure("<?xml ='1.0'?>\n<doc/>\n", XML_ERROR_XML_DECL,
1409 "Failed to report missing XML declaration attribute");
1410 }
1411 END_TEST
1412
START_TEST(test_xmldecl_missing_value)1413 START_TEST(test_xmldecl_missing_value) {
1414 expect_failure("<?xml version='1.0' encoding='us-ascii' standalone?>\n"
1415 "<doc/>",
1416 XML_ERROR_XML_DECL,
1417 "Failed to report missing attribute value");
1418 }
1419 END_TEST
1420
1421 /* Regression test for SF bug #584832. */
1422 static int XMLCALL
UnknownEncodingHandler(void * data,const XML_Char * encoding,XML_Encoding * info)1423 UnknownEncodingHandler(void *data, const XML_Char *encoding,
1424 XML_Encoding *info) {
1425 UNUSED_P(data);
1426 if (xcstrcmp(encoding, XCS("unsupported-encoding")) == 0) {
1427 int i;
1428 for (i = 0; i < 256; ++i)
1429 info->map[i] = i;
1430 info->data = NULL;
1431 info->convert = NULL;
1432 info->release = NULL;
1433 return XML_STATUS_OK;
1434 }
1435 return XML_STATUS_ERROR;
1436 }
1437
START_TEST(test_unknown_encoding_internal_entity)1438 START_TEST(test_unknown_encoding_internal_entity) {
1439 const char *text = "<?xml version='1.0' encoding='unsupported-encoding'?>\n"
1440 "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n"
1441 "<test a='&foo;'/>";
1442
1443 XML_SetUnknownEncodingHandler(g_parser, UnknownEncodingHandler, NULL);
1444 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1445 == XML_STATUS_ERROR)
1446 xml_failure(g_parser);
1447 }
1448 END_TEST
1449
1450 /* Test unrecognised encoding handler */
1451 static void
dummy_release(void * data)1452 dummy_release(void *data) {
1453 UNUSED_P(data);
1454 }
1455
1456 static int XMLCALL
UnrecognisedEncodingHandler(void * data,const XML_Char * encoding,XML_Encoding * info)1457 UnrecognisedEncodingHandler(void *data, const XML_Char *encoding,
1458 XML_Encoding *info) {
1459 UNUSED_P(data);
1460 UNUSED_P(encoding);
1461 info->data = NULL;
1462 info->convert = NULL;
1463 info->release = dummy_release;
1464 return XML_STATUS_ERROR;
1465 }
1466
START_TEST(test_unrecognised_encoding_internal_entity)1467 START_TEST(test_unrecognised_encoding_internal_entity) {
1468 const char *text = "<?xml version='1.0' encoding='unsupported-encoding'?>\n"
1469 "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n"
1470 "<test a='&foo;'/>";
1471
1472 XML_SetUnknownEncodingHandler(g_parser, UnrecognisedEncodingHandler, NULL);
1473 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1474 != XML_STATUS_ERROR)
1475 fail("Unrecognised encoding not rejected");
1476 }
1477 END_TEST
1478
1479 /* Regression test for SF bug #620106. */
1480 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)1481 external_entity_loader(XML_Parser parser, const XML_Char *context,
1482 const XML_Char *base, const XML_Char *systemId,
1483 const XML_Char *publicId) {
1484 ExtTest *test_data = (ExtTest *)XML_GetUserData(parser);
1485 XML_Parser extparser;
1486
1487 UNUSED_P(base);
1488 UNUSED_P(systemId);
1489 UNUSED_P(publicId);
1490 extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
1491 if (extparser == NULL)
1492 fail("Could not create external entity parser.");
1493 if (test_data->encoding != NULL) {
1494 if (! XML_SetEncoding(extparser, test_data->encoding))
1495 fail("XML_SetEncoding() ignored for external entity");
1496 }
1497 if (_XML_Parse_SINGLE_BYTES(extparser, test_data->parse_text,
1498 (int)strlen(test_data->parse_text), XML_TRUE)
1499 == XML_STATUS_ERROR) {
1500 xml_failure(extparser);
1501 return XML_STATUS_ERROR;
1502 }
1503 XML_ParserFree(extparser);
1504 return XML_STATUS_OK;
1505 }
1506
START_TEST(test_ext_entity_set_encoding)1507 START_TEST(test_ext_entity_set_encoding) {
1508 const char *text = "<!DOCTYPE doc [\n"
1509 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1510 "]>\n"
1511 "<doc>&en;</doc>";
1512 ExtTest test_data
1513 = {/* This text says it's an unsupported encoding, but it's really
1514 UTF-8, which we tell Expat using XML_SetEncoding().
1515 */
1516 "<?xml encoding='iso-8859-3'?>\xC3\xA9", XCS("utf-8"), NULL};
1517 #ifdef XML_UNICODE
1518 const XML_Char *expected = XCS("\x00e9");
1519 #else
1520 const XML_Char *expected = XCS("\xc3\xa9");
1521 #endif
1522
1523 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1524 run_ext_character_check(text, &test_data, expected);
1525 }
1526 END_TEST
1527
1528 /* Test external entities with no handler */
START_TEST(test_ext_entity_no_handler)1529 START_TEST(test_ext_entity_no_handler) {
1530 const char *text = "<!DOCTYPE doc [\n"
1531 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1532 "]>\n"
1533 "<doc>&en;</doc>";
1534
1535 XML_SetDefaultHandler(g_parser, dummy_default_handler);
1536 run_character_check(text, XCS(""));
1537 }
1538 END_TEST
1539
1540 /* Test UTF-8 BOM is accepted */
START_TEST(test_ext_entity_set_bom)1541 START_TEST(test_ext_entity_set_bom) {
1542 const char *text = "<!DOCTYPE doc [\n"
1543 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1544 "]>\n"
1545 "<doc>&en;</doc>";
1546 ExtTest test_data = {"\xEF\xBB\xBF" /* BOM */
1547 "<?xml encoding='iso-8859-3'?>"
1548 "\xC3\xA9",
1549 XCS("utf-8"), NULL};
1550 #ifdef XML_UNICODE
1551 const XML_Char *expected = XCS("\x00e9");
1552 #else
1553 const XML_Char *expected = XCS("\xc3\xa9");
1554 #endif
1555
1556 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1557 run_ext_character_check(text, &test_data, expected);
1558 }
1559 END_TEST
1560
1561 /* Test that bad encodings are faulted */
1562 typedef struct ext_faults {
1563 const char *parse_text;
1564 const char *fail_text;
1565 const XML_Char *encoding;
1566 enum XML_Error error;
1567 } ExtFaults;
1568
1569 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)1570 external_entity_faulter(XML_Parser parser, const XML_Char *context,
1571 const XML_Char *base, const XML_Char *systemId,
1572 const XML_Char *publicId) {
1573 XML_Parser ext_parser;
1574 ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser);
1575
1576 UNUSED_P(base);
1577 UNUSED_P(systemId);
1578 UNUSED_P(publicId);
1579 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
1580 if (ext_parser == NULL)
1581 fail("Could not create external entity parser");
1582 if (fault->encoding != NULL) {
1583 if (! XML_SetEncoding(ext_parser, fault->encoding))
1584 fail("XML_SetEncoding failed");
1585 }
1586 if (_XML_Parse_SINGLE_BYTES(ext_parser, fault->parse_text,
1587 (int)strlen(fault->parse_text), XML_TRUE)
1588 != XML_STATUS_ERROR)
1589 fail(fault->fail_text);
1590 if (XML_GetErrorCode(ext_parser) != fault->error)
1591 xml_failure(ext_parser);
1592
1593 XML_ParserFree(ext_parser);
1594 return XML_STATUS_ERROR;
1595 }
1596
START_TEST(test_ext_entity_bad_encoding)1597 START_TEST(test_ext_entity_bad_encoding) {
1598 const char *text = "<!DOCTYPE doc [\n"
1599 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1600 "]>\n"
1601 "<doc>&en;</doc>";
1602 ExtFaults fault
1603 = {"<?xml encoding='iso-8859-3'?>u", "Unsupported encoding not faulted",
1604 XCS("unknown"), XML_ERROR_UNKNOWN_ENCODING};
1605
1606 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
1607 XML_SetUserData(g_parser, &fault);
1608 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
1609 "Bad encoding should not have been accepted");
1610 }
1611 END_TEST
1612
1613 /* Try handing an invalid encoding to an external entity parser */
START_TEST(test_ext_entity_bad_encoding_2)1614 START_TEST(test_ext_entity_bad_encoding_2) {
1615 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
1616 "<!DOCTYPE doc SYSTEM 'foo'>\n"
1617 "<doc>&entity;</doc>";
1618 ExtFaults fault
1619 = {"<!ELEMENT doc (#PCDATA)*>", "Unknown encoding not faulted",
1620 XCS("unknown-encoding"), XML_ERROR_UNKNOWN_ENCODING};
1621
1622 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1623 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
1624 XML_SetUserData(g_parser, &fault);
1625 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
1626 "Bad encoding not faulted in external entity handler");
1627 }
1628 END_TEST
1629
1630 /* Test that no error is reported for unknown entities if we don't
1631 read an external subset. This was fixed in Expat 1.95.5.
1632 */
START_TEST(test_wfc_undeclared_entity_unread_external_subset)1633 START_TEST(test_wfc_undeclared_entity_unread_external_subset) {
1634 const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
1635 "<doc>&entity;</doc>";
1636
1637 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1638 == XML_STATUS_ERROR)
1639 xml_failure(g_parser);
1640 }
1641 END_TEST
1642
1643 /* Test that an error is reported for unknown entities if we don't
1644 have an external subset.
1645 */
START_TEST(test_wfc_undeclared_entity_no_external_subset)1646 START_TEST(test_wfc_undeclared_entity_no_external_subset) {
1647 expect_failure("<doc>&entity;</doc>", XML_ERROR_UNDEFINED_ENTITY,
1648 "Parser did not report undefined entity w/out a DTD.");
1649 }
1650 END_TEST
1651
1652 /* Test that an error is reported for unknown entities if we don't
1653 read an external subset, but have been declared standalone.
1654 */
START_TEST(test_wfc_undeclared_entity_standalone)1655 START_TEST(test_wfc_undeclared_entity_standalone) {
1656 const char *text
1657 = "<?xml version='1.0' encoding='us-ascii' standalone='yes'?>\n"
1658 "<!DOCTYPE doc SYSTEM 'foo'>\n"
1659 "<doc>&entity;</doc>";
1660
1661 expect_failure(text, XML_ERROR_UNDEFINED_ENTITY,
1662 "Parser did not report undefined entity (standalone).");
1663 }
1664 END_TEST
1665
1666 /* Test that an error is reported for unknown entities if we have read
1667 an external subset, and standalone is true.
1668 */
START_TEST(test_wfc_undeclared_entity_with_external_subset_standalone)1669 START_TEST(test_wfc_undeclared_entity_with_external_subset_standalone) {
1670 const char *text
1671 = "<?xml version='1.0' encoding='us-ascii' standalone='yes'?>\n"
1672 "<!DOCTYPE doc SYSTEM 'foo'>\n"
1673 "<doc>&entity;</doc>";
1674 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
1675
1676 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1677 XML_SetUserData(g_parser, &test_data);
1678 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1679 expect_failure(text, XML_ERROR_UNDEFINED_ENTITY,
1680 "Parser did not report undefined entity (external DTD).");
1681 }
1682 END_TEST
1683
1684 /* Test that external entity handling is not done if the parsing flag
1685 * is set to UNLESS_STANDALONE
1686 */
START_TEST(test_entity_with_external_subset_unless_standalone)1687 START_TEST(test_entity_with_external_subset_unless_standalone) {
1688 const char *text
1689 = "<?xml version='1.0' encoding='us-ascii' standalone='yes'?>\n"
1690 "<!DOCTYPE doc SYSTEM 'foo'>\n"
1691 "<doc>&entity;</doc>";
1692 ExtTest test_data = {"<!ENTITY entity 'bar'>", NULL, NULL};
1693
1694 XML_SetParamEntityParsing(g_parser,
1695 XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE);
1696 XML_SetUserData(g_parser, &test_data);
1697 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1698 expect_failure(text, XML_ERROR_UNDEFINED_ENTITY,
1699 "Parser did not report undefined entity");
1700 }
1701 END_TEST
1702
1703 /* Test that no error is reported for unknown entities if we have read
1704 an external subset, and standalone is false.
1705 */
START_TEST(test_wfc_undeclared_entity_with_external_subset)1706 START_TEST(test_wfc_undeclared_entity_with_external_subset) {
1707 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
1708 "<!DOCTYPE doc SYSTEM 'foo'>\n"
1709 "<doc>&entity;</doc>";
1710 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
1711
1712 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1713 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1714 run_ext_character_check(text, &test_data, XCS(""));
1715 }
1716 END_TEST
1717
1718 /* Test that an error is reported if our NotStandalone handler fails */
1719 static int XMLCALL
reject_not_standalone_handler(void * userData)1720 reject_not_standalone_handler(void *userData) {
1721 UNUSED_P(userData);
1722 return XML_STATUS_ERROR;
1723 }
1724
START_TEST(test_not_standalone_handler_reject)1725 START_TEST(test_not_standalone_handler_reject) {
1726 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
1727 "<!DOCTYPE doc SYSTEM 'foo'>\n"
1728 "<doc>&entity;</doc>";
1729 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
1730
1731 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1732 XML_SetUserData(g_parser, &test_data);
1733 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1734 XML_SetNotStandaloneHandler(g_parser, reject_not_standalone_handler);
1735 expect_failure(text, XML_ERROR_NOT_STANDALONE,
1736 "NotStandalone handler failed to reject");
1737
1738 /* Try again but without external entity handling */
1739 XML_ParserReset(g_parser, NULL);
1740 XML_SetNotStandaloneHandler(g_parser, reject_not_standalone_handler);
1741 expect_failure(text, XML_ERROR_NOT_STANDALONE,
1742 "NotStandalone handler failed to reject");
1743 }
1744 END_TEST
1745
1746 /* Test that no error is reported if our NotStandalone handler succeeds */
1747 static int XMLCALL
accept_not_standalone_handler(void * userData)1748 accept_not_standalone_handler(void *userData) {
1749 UNUSED_P(userData);
1750 return XML_STATUS_OK;
1751 }
1752
START_TEST(test_not_standalone_handler_accept)1753 START_TEST(test_not_standalone_handler_accept) {
1754 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
1755 "<!DOCTYPE doc SYSTEM 'foo'>\n"
1756 "<doc>&entity;</doc>";
1757 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
1758
1759 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1760 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1761 XML_SetNotStandaloneHandler(g_parser, accept_not_standalone_handler);
1762 run_ext_character_check(text, &test_data, XCS(""));
1763
1764 /* Repeat without the external entity handler */
1765 XML_ParserReset(g_parser, NULL);
1766 XML_SetNotStandaloneHandler(g_parser, accept_not_standalone_handler);
1767 run_character_check(text, XCS(""));
1768 }
1769 END_TEST
1770
START_TEST(test_wfc_no_recursive_entity_refs)1771 START_TEST(test_wfc_no_recursive_entity_refs) {
1772 const char *text = "<!DOCTYPE doc [\n"
1773 " <!ENTITY entity '&entity;'>\n"
1774 "]>\n"
1775 "<doc>&entity;</doc>";
1776
1777 expect_failure(text, XML_ERROR_RECURSIVE_ENTITY_REF,
1778 "Parser did not report recursive entity reference.");
1779 }
1780 END_TEST
1781
1782 /* Test incomplete external entities are faulted */
START_TEST(test_ext_entity_invalid_parse)1783 START_TEST(test_ext_entity_invalid_parse) {
1784 const char *text = "<!DOCTYPE doc [\n"
1785 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1786 "]>\n"
1787 "<doc>&en;</doc>";
1788 const ExtFaults faults[]
1789 = {{"<", "Incomplete element declaration not faulted", NULL,
1790 XML_ERROR_UNCLOSED_TOKEN},
1791 {"<\xe2\x82", /* First two bytes of a three-byte char */
1792 "Incomplete character not faulted", NULL, XML_ERROR_PARTIAL_CHAR},
1793 {"<tag>\xe2\x82", "Incomplete character in CDATA not faulted", NULL,
1794 XML_ERROR_PARTIAL_CHAR},
1795 {NULL, NULL, NULL, XML_ERROR_NONE}};
1796 const ExtFaults *fault = faults;
1797
1798 for (; fault->parse_text != NULL; fault++) {
1799 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1800 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
1801 XML_SetUserData(g_parser, (void *)fault);
1802 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
1803 "Parser did not report external entity error");
1804 XML_ParserReset(g_parser, NULL);
1805 }
1806 }
1807 END_TEST
1808
1809 /* Regression test for SF bug #483514. */
START_TEST(test_dtd_default_handling)1810 START_TEST(test_dtd_default_handling) {
1811 const char *text = "<!DOCTYPE doc [\n"
1812 "<!ENTITY e SYSTEM 'http://example.org/e'>\n"
1813 "<!NOTATION n SYSTEM 'http://example.org/n'>\n"
1814 "<!ELEMENT doc EMPTY>\n"
1815 "<!ATTLIST doc a CDATA #IMPLIED>\n"
1816 "<?pi in dtd?>\n"
1817 "<!--comment in dtd-->\n"
1818 "]><doc/>";
1819
1820 XML_SetDefaultHandler(g_parser, accumulate_characters);
1821 XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler);
1822 XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler);
1823 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
1824 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
1825 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
1826 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
1827 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
1828 XML_SetCommentHandler(g_parser, dummy_comment_handler);
1829 XML_SetStartCdataSectionHandler(g_parser, dummy_start_cdata_handler);
1830 XML_SetEndCdataSectionHandler(g_parser, dummy_end_cdata_handler);
1831 run_character_check(text, XCS("\n\n\n\n\n\n\n<doc/>"));
1832 }
1833 END_TEST
1834
1835 /* Test handling of attribute declarations */
1836 typedef struct AttTest {
1837 const char *definition;
1838 const XML_Char *element_name;
1839 const XML_Char *attr_name;
1840 const XML_Char *attr_type;
1841 const XML_Char *default_value;
1842 int is_required;
1843 } AttTest;
1844
1845 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)1846 verify_attlist_decl_handler(void *userData, const XML_Char *element_name,
1847 const XML_Char *attr_name,
1848 const XML_Char *attr_type,
1849 const XML_Char *default_value, int is_required) {
1850 AttTest *at = (AttTest *)userData;
1851
1852 if (xcstrcmp(element_name, at->element_name))
1853 fail("Unexpected element name in attribute declaration");
1854 if (xcstrcmp(attr_name, at->attr_name))
1855 fail("Unexpected attribute name in attribute declaration");
1856 if (xcstrcmp(attr_type, at->attr_type))
1857 fail("Unexpected attribute type in attribute declaration");
1858 if ((default_value == NULL && at->default_value != NULL)
1859 || (default_value != NULL && at->default_value == NULL)
1860 || (default_value != NULL && xcstrcmp(default_value, at->default_value)))
1861 fail("Unexpected default value in attribute declaration");
1862 if (is_required != at->is_required)
1863 fail("Requirement mismatch in attribute declaration");
1864 }
1865
START_TEST(test_dtd_attr_handling)1866 START_TEST(test_dtd_attr_handling) {
1867 const char *prolog = "<!DOCTYPE doc [\n"
1868 "<!ELEMENT doc EMPTY>\n";
1869 AttTest attr_data[]
1870 = {{"<!ATTLIST doc a ( one | two | three ) #REQUIRED>\n"
1871 "]>"
1872 "<doc a='two'/>",
1873 XCS("doc"), XCS("a"),
1874 XCS("(one|two|three)"), /* Extraneous spaces will be removed */
1875 NULL, XML_TRUE},
1876 {"<!NOTATION foo SYSTEM 'http://example.org/foo'>\n"
1877 "<!ATTLIST doc a NOTATION (foo) #IMPLIED>\n"
1878 "]>"
1879 "<doc/>",
1880 XCS("doc"), XCS("a"), XCS("NOTATION(foo)"), NULL, XML_FALSE},
1881 {"<!ATTLIST doc a NOTATION (foo) 'bar'>\n"
1882 "]>"
1883 "<doc/>",
1884 XCS("doc"), XCS("a"), XCS("NOTATION(foo)"), XCS("bar"), XML_FALSE},
1885 {"<!ATTLIST doc a CDATA '\xdb\xb2'>\n"
1886 "]>"
1887 "<doc/>",
1888 XCS("doc"), XCS("a"), XCS("CDATA"),
1889 #ifdef XML_UNICODE
1890 XCS("\x06f2"),
1891 #else
1892 XCS("\xdb\xb2"),
1893 #endif
1894 XML_FALSE},
1895 {NULL, NULL, NULL, NULL, NULL, XML_FALSE}};
1896 AttTest *test;
1897
1898 for (test = attr_data; test->definition != NULL; test++) {
1899 XML_SetAttlistDeclHandler(g_parser, verify_attlist_decl_handler);
1900 XML_SetUserData(g_parser, test);
1901 if (_XML_Parse_SINGLE_BYTES(g_parser, prolog, (int)strlen(prolog),
1902 XML_FALSE)
1903 == XML_STATUS_ERROR)
1904 xml_failure(g_parser);
1905 if (_XML_Parse_SINGLE_BYTES(g_parser, test->definition,
1906 (int)strlen(test->definition), XML_TRUE)
1907 == XML_STATUS_ERROR)
1908 xml_failure(g_parser);
1909 XML_ParserReset(g_parser, NULL);
1910 }
1911 }
1912 END_TEST
1913
1914 /* See related SF bug #673791.
1915 When namespace processing is enabled, setting the namespace URI for
1916 a prefix is not allowed; this test ensures that it *is* allowed
1917 when namespace processing is not enabled.
1918 (See Namespaces in XML, section 2.)
1919 */
START_TEST(test_empty_ns_without_namespaces)1920 START_TEST(test_empty_ns_without_namespaces) {
1921 const char *text = "<doc xmlns:prefix='http://example.org/'>\n"
1922 " <e xmlns:prefix=''/>\n"
1923 "</doc>";
1924
1925 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1926 == XML_STATUS_ERROR)
1927 xml_failure(g_parser);
1928 }
1929 END_TEST
1930
1931 /* Regression test for SF bug #824420.
1932 Checks that an xmlns:prefix attribute set in an attribute's default
1933 value isn't misinterpreted.
1934 */
START_TEST(test_ns_in_attribute_default_without_namespaces)1935 START_TEST(test_ns_in_attribute_default_without_namespaces) {
1936 const char *text = "<!DOCTYPE e:element [\n"
1937 " <!ATTLIST e:element\n"
1938 " xmlns:e CDATA 'http://example.org/'>\n"
1939 " ]>\n"
1940 "<e:element/>";
1941
1942 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1943 == XML_STATUS_ERROR)
1944 xml_failure(g_parser);
1945 }
1946 END_TEST
1947
1948 static const char *long_character_data_text
1949 = "<?xml version='1.0' encoding='iso-8859-1'?><s>"
1950 "012345678901234567890123456789012345678901234567890123456789"
1951 "012345678901234567890123456789012345678901234567890123456789"
1952 "012345678901234567890123456789012345678901234567890123456789"
1953 "012345678901234567890123456789012345678901234567890123456789"
1954 "012345678901234567890123456789012345678901234567890123456789"
1955 "012345678901234567890123456789012345678901234567890123456789"
1956 "012345678901234567890123456789012345678901234567890123456789"
1957 "012345678901234567890123456789012345678901234567890123456789"
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 "</s>";
1971
1972 static XML_Bool resumable = XML_FALSE;
1973
1974 static void
clearing_aborting_character_handler(void * userData,const XML_Char * s,int len)1975 clearing_aborting_character_handler(void *userData, const XML_Char *s,
1976 int len) {
1977 UNUSED_P(userData);
1978 UNUSED_P(s);
1979 UNUSED_P(len);
1980 XML_StopParser(g_parser, resumable);
1981 XML_SetCharacterDataHandler(g_parser, NULL);
1982 }
1983
1984 /* Regression test for SF bug #1515266: missing check of stopped
1985 parser in doContext() 'for' loop. */
START_TEST(test_stop_parser_between_char_data_calls)1986 START_TEST(test_stop_parser_between_char_data_calls) {
1987 /* The sample data must be big enough that there are two calls to
1988 the character data handler from within the inner "for" loop of
1989 the XML_TOK_DATA_CHARS case in doContent(), and the character
1990 handler must stop the parser and clear the character data
1991 handler.
1992 */
1993 const char *text = long_character_data_text;
1994
1995 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
1996 resumable = XML_FALSE;
1997 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1998 != XML_STATUS_ERROR)
1999 xml_failure(g_parser);
2000 if (XML_GetErrorCode(g_parser) != XML_ERROR_ABORTED)
2001 xml_failure(g_parser);
2002 }
2003 END_TEST
2004
2005 /* Regression test for SF bug #1515266: missing check of stopped
2006 parser in doContext() 'for' loop. */
START_TEST(test_suspend_parser_between_char_data_calls)2007 START_TEST(test_suspend_parser_between_char_data_calls) {
2008 /* The sample data must be big enough that there are two calls to
2009 the character data handler from within the inner "for" loop of
2010 the XML_TOK_DATA_CHARS case in doContent(), and the character
2011 handler must stop the parser and clear the character data
2012 handler.
2013 */
2014 const char *text = long_character_data_text;
2015
2016 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2017 resumable = XML_TRUE;
2018 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2019 != XML_STATUS_SUSPENDED)
2020 xml_failure(g_parser);
2021 if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE)
2022 xml_failure(g_parser);
2023 /* Try parsing directly */
2024 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
2025 != XML_STATUS_ERROR)
2026 fail("Attempt to continue parse while suspended not faulted");
2027 if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED)
2028 fail("Suspended parse not faulted with correct error");
2029 }
2030 END_TEST
2031
2032 static XML_Bool abortable = XML_FALSE;
2033
2034 static void
parser_stop_character_handler(void * userData,const XML_Char * s,int len)2035 parser_stop_character_handler(void *userData, const XML_Char *s, int len) {
2036 UNUSED_P(userData);
2037 UNUSED_P(s);
2038 UNUSED_P(len);
2039 XML_StopParser(g_parser, resumable);
2040 XML_SetCharacterDataHandler(g_parser, NULL);
2041 if (! resumable) {
2042 /* Check that aborting an aborted parser is faulted */
2043 if (XML_StopParser(g_parser, XML_FALSE) != XML_STATUS_ERROR)
2044 fail("Aborting aborted parser not faulted");
2045 if (XML_GetErrorCode(g_parser) != XML_ERROR_FINISHED)
2046 xml_failure(g_parser);
2047 } else if (abortable) {
2048 /* Check that aborting a suspended parser works */
2049 if (XML_StopParser(g_parser, XML_FALSE) == XML_STATUS_ERROR)
2050 xml_failure(g_parser);
2051 } else {
2052 /* Check that suspending a suspended parser works */
2053 if (XML_StopParser(g_parser, XML_TRUE) != XML_STATUS_ERROR)
2054 fail("Suspending suspended parser not faulted");
2055 if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED)
2056 xml_failure(g_parser);
2057 }
2058 }
2059
2060 /* Test repeated calls to XML_StopParser are handled correctly */
START_TEST(test_repeated_stop_parser_between_char_data_calls)2061 START_TEST(test_repeated_stop_parser_between_char_data_calls) {
2062 const char *text = long_character_data_text;
2063
2064 XML_SetCharacterDataHandler(g_parser, parser_stop_character_handler);
2065 resumable = XML_FALSE;
2066 abortable = XML_FALSE;
2067 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2068 != XML_STATUS_ERROR)
2069 fail("Failed to double-stop parser");
2070
2071 XML_ParserReset(g_parser, NULL);
2072 XML_SetCharacterDataHandler(g_parser, parser_stop_character_handler);
2073 resumable = XML_TRUE;
2074 abortable = XML_FALSE;
2075 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2076 != XML_STATUS_SUSPENDED)
2077 fail("Failed to double-suspend parser");
2078
2079 XML_ParserReset(g_parser, NULL);
2080 XML_SetCharacterDataHandler(g_parser, parser_stop_character_handler);
2081 resumable = XML_TRUE;
2082 abortable = XML_TRUE;
2083 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2084 != XML_STATUS_ERROR)
2085 fail("Failed to suspend-abort parser");
2086 }
2087 END_TEST
2088
START_TEST(test_good_cdata_ascii)2089 START_TEST(test_good_cdata_ascii) {
2090 const char *text = "<a><![CDATA[<greeting>Hello, world!</greeting>]]></a>";
2091 const XML_Char *expected = XCS("<greeting>Hello, world!</greeting>");
2092
2093 CharData storage;
2094 CharData_Init(&storage);
2095 XML_SetUserData(g_parser, &storage);
2096 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2097 /* Add start and end handlers for coverage */
2098 XML_SetStartCdataSectionHandler(g_parser, dummy_start_cdata_handler);
2099 XML_SetEndCdataSectionHandler(g_parser, dummy_end_cdata_handler);
2100
2101 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2102 == XML_STATUS_ERROR)
2103 xml_failure(g_parser);
2104 CharData_CheckXMLChars(&storage, expected);
2105
2106 /* Try again, this time with a default handler */
2107 XML_ParserReset(g_parser, NULL);
2108 CharData_Init(&storage);
2109 XML_SetUserData(g_parser, &storage);
2110 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2111 XML_SetDefaultHandler(g_parser, dummy_default_handler);
2112
2113 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2114 == XML_STATUS_ERROR)
2115 xml_failure(g_parser);
2116 CharData_CheckXMLChars(&storage, expected);
2117 }
2118 END_TEST
2119
START_TEST(test_good_cdata_utf16)2120 START_TEST(test_good_cdata_utf16) {
2121 /* Test data is:
2122 * <?xml version='1.0' encoding='utf-16'?>
2123 * <a><![CDATA[hello]]></a>
2124 */
2125 const char text[]
2126 = "\0<\0?\0x\0m\0l\0"
2127 " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2128 " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0"
2129 "1\0"
2130 "6\0'"
2131 "\0?\0>\0\n"
2132 "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0[\0h\0e\0l\0l\0o\0]\0]\0>\0<\0/\0a\0>";
2133 const XML_Char *expected = XCS("hello");
2134
2135 CharData storage;
2136 CharData_Init(&storage);
2137 XML_SetUserData(g_parser, &storage);
2138 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2139
2140 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
2141 == XML_STATUS_ERROR)
2142 xml_failure(g_parser);
2143 CharData_CheckXMLChars(&storage, expected);
2144 }
2145 END_TEST
2146
START_TEST(test_good_cdata_utf16_le)2147 START_TEST(test_good_cdata_utf16_le) {
2148 /* Test data is:
2149 * <?xml version='1.0' encoding='utf-16'?>
2150 * <a><![CDATA[hello]]></a>
2151 */
2152 const char text[]
2153 = "<\0?\0x\0m\0l\0"
2154 " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2155 " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0"
2156 "1\0"
2157 "6\0'"
2158 "\0?\0>\0\n"
2159 "\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";
2160 const XML_Char *expected = XCS("hello");
2161
2162 CharData storage;
2163 CharData_Init(&storage);
2164 XML_SetUserData(g_parser, &storage);
2165 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2166
2167 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
2168 == XML_STATUS_ERROR)
2169 xml_failure(g_parser);
2170 CharData_CheckXMLChars(&storage, expected);
2171 }
2172 END_TEST
2173
2174 /* Test UTF16 conversion of a long cdata string */
2175
2176 /* 16 characters: handy macro to reduce visual clutter */
2177 #define A_TO_P_IN_UTF16 "\0A\0B\0C\0D\0E\0F\0G\0H\0I\0J\0K\0L\0M\0N\0O\0P"
2178
START_TEST(test_long_cdata_utf16)2179 START_TEST(test_long_cdata_utf16) {
2180 /* Test data is:
2181 * <?xlm version='1.0' encoding='utf-16'?>
2182 * <a><![CDATA[
2183 * ABCDEFGHIJKLMNOP
2184 * ]]></a>
2185 */
2186 const char text[]
2187 = "\0<\0?\0x\0m\0l\0 "
2188 "\0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0 "
2189 "\0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0\x31\0\x36\0'\0?\0>"
2190 "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0["
2191 /* 64 characters per line */
2192 /* clang-format off */
2193 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
2194 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
2195 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
2196 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
2197 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
2198 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
2199 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
2200 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16
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
2210 /* clang-format on */
2211 "\0]\0]\0>\0<\0/\0a\0>";
2212 const XML_Char *expected =
2213 /* clang-format off */
2214 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2215 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2216 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2217 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2218 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2219 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2220 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2221 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
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("ABCDEFGHIJKLMNOP");
2231 /* clang-format on */
2232 CharData storage;
2233 void *buffer;
2234
2235 CharData_Init(&storage);
2236 XML_SetUserData(g_parser, &storage);
2237 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2238 buffer = XML_GetBuffer(g_parser, sizeof(text) - 1);
2239 if (buffer == NULL)
2240 fail("Could not allocate parse buffer");
2241 assert(buffer != NULL);
2242 memcpy(buffer, text, sizeof(text) - 1);
2243 if (XML_ParseBuffer(g_parser, sizeof(text) - 1, XML_TRUE) == XML_STATUS_ERROR)
2244 xml_failure(g_parser);
2245 CharData_CheckXMLChars(&storage, expected);
2246 }
2247 END_TEST
2248
2249 /* Test handling of multiple unit UTF-16 characters */
2250 #ifndef XML_MIN_SIZE /* FIXME workaround -DXML_MIN_SIZE + ASan (issue #332) */
START_TEST(test_multichar_cdata_utf16)2251 START_TEST(test_multichar_cdata_utf16) {
2252 /* Test data is:
2253 * <?xml version='1.0' encoding='utf-16'?>
2254 * <a><![CDATA[{MINIM}{CROTCHET}]]></a>
2255 *
2256 * where {MINIM} is U+1d15e (a minim or half-note)
2257 * UTF-16: 0xd834 0xdd5e
2258 * UTF-8: 0xf0 0x9d 0x85 0x9e
2259 * and {CROTCHET} is U+1d15f (a crotchet or quarter-note)
2260 * UTF-16: 0xd834 0xdd5f
2261 * UTF-8: 0xf0 0x9d 0x85 0x9f
2262 */
2263 const char text[] = "\0<\0?\0x\0m\0l\0"
2264 " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2265 " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0"
2266 "1\0"
2267 "6\0'"
2268 "\0?\0>\0\n"
2269 "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0["
2270 "\xd8\x34\xdd\x5e\xd8\x34\xdd\x5f"
2271 "\0]\0]\0>\0<\0/\0a\0>";
2272 # ifdef XML_UNICODE
2273 const XML_Char *expected = XCS("\xd834\xdd5e\xd834\xdd5f");
2274 # else
2275 const XML_Char *expected = XCS("\xf0\x9d\x85\x9e\xf0\x9d\x85\x9f");
2276 # endif
2277 CharData storage;
2278
2279 CharData_Init(&storage);
2280 XML_SetUserData(g_parser, &storage);
2281 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2282
2283 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
2284 == XML_STATUS_ERROR)
2285 xml_failure(g_parser);
2286 CharData_CheckXMLChars(&storage, expected);
2287 }
2288 END_TEST
2289 #endif /* ifndef XML_MIN_SIZE */
2290
2291 /* Test that an element name with a UTF-16 surrogate pair is rejected */
START_TEST(test_utf16_bad_surrogate_pair)2292 START_TEST(test_utf16_bad_surrogate_pair) {
2293 /* Test data is:
2294 * <?xml version='1.0' encoding='utf-16'?>
2295 * <a><![CDATA[{BADLINB}]]></a>
2296 *
2297 * where {BADLINB} is U+10000 (the first Linear B character)
2298 * with the UTF-16 surrogate pair in the wrong order, i.e.
2299 * 0xdc00 0xd800
2300 */
2301 const char text[] = "\0<\0?\0x\0m\0l\0"
2302 " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2303 " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0"
2304 "1\0"
2305 "6\0'"
2306 "\0?\0>\0\n"
2307 "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0["
2308 "\xdc\x00\xd8\x00"
2309 "\0]\0]\0>\0<\0/\0a\0>";
2310
2311 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
2312 != XML_STATUS_ERROR)
2313 fail("Reversed UTF-16 surrogate pair not faulted");
2314 if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
2315 xml_failure(g_parser);
2316 }
2317 END_TEST
2318
START_TEST(test_bad_cdata)2319 START_TEST(test_bad_cdata) {
2320 struct CaseData {
2321 const char *text;
2322 enum XML_Error expectedError;
2323 };
2324
2325 struct CaseData cases[]
2326 = {{"<a><", XML_ERROR_UNCLOSED_TOKEN},
2327 {"<a><!", XML_ERROR_UNCLOSED_TOKEN},
2328 {"<a><![", XML_ERROR_UNCLOSED_TOKEN},
2329 {"<a><![C", XML_ERROR_UNCLOSED_TOKEN},
2330 {"<a><![CD", XML_ERROR_UNCLOSED_TOKEN},
2331 {"<a><![CDA", XML_ERROR_UNCLOSED_TOKEN},
2332 {"<a><![CDAT", XML_ERROR_UNCLOSED_TOKEN},
2333 {"<a><![CDATA", XML_ERROR_UNCLOSED_TOKEN},
2334
2335 {"<a><![CDATA[", XML_ERROR_UNCLOSED_CDATA_SECTION},
2336 {"<a><![CDATA[]", XML_ERROR_UNCLOSED_CDATA_SECTION},
2337 {"<a><![CDATA[]]", XML_ERROR_UNCLOSED_CDATA_SECTION},
2338
2339 {"<a><!<a/>", XML_ERROR_INVALID_TOKEN},
2340 {"<a><![<a/>", XML_ERROR_UNCLOSED_TOKEN}, /* ?! */
2341 {"<a><![C<a/>", XML_ERROR_UNCLOSED_TOKEN}, /* ?! */
2342 {"<a><![CD<a/>", XML_ERROR_INVALID_TOKEN},
2343 {"<a><![CDA<a/>", XML_ERROR_INVALID_TOKEN},
2344 {"<a><![CDAT<a/>", XML_ERROR_INVALID_TOKEN},
2345 {"<a><![CDATA<a/>", XML_ERROR_INVALID_TOKEN},
2346
2347 {"<a><![CDATA[<a/>", XML_ERROR_UNCLOSED_CDATA_SECTION},
2348 {"<a><![CDATA[]<a/>", XML_ERROR_UNCLOSED_CDATA_SECTION},
2349 {"<a><![CDATA[]]<a/>", XML_ERROR_UNCLOSED_CDATA_SECTION}};
2350
2351 size_t i = 0;
2352 for (; i < sizeof(cases) / sizeof(struct CaseData); i++) {
2353 const enum XML_Status actualStatus = _XML_Parse_SINGLE_BYTES(
2354 g_parser, cases[i].text, (int)strlen(cases[i].text), XML_TRUE);
2355 const enum XML_Error actualError = XML_GetErrorCode(g_parser);
2356
2357 assert(actualStatus == XML_STATUS_ERROR);
2358
2359 if (actualError != cases[i].expectedError) {
2360 char message[100];
2361 sprintf(message,
2362 "Expected error %d but got error %d for case %u: \"%s\"\n",
2363 cases[i].expectedError, actualError, (unsigned int)i + 1,
2364 cases[i].text);
2365 fail(message);
2366 }
2367
2368 XML_ParserReset(g_parser, NULL);
2369 }
2370 }
2371 END_TEST
2372
2373 /* Test failures in UTF-16 CDATA */
2374 #ifndef XML_MIN_SIZE /* FIXME workaround -DXML_MIN_SIZE + ASan (issue #332) */
START_TEST(test_bad_cdata_utf16)2375 START_TEST(test_bad_cdata_utf16) {
2376 struct CaseData {
2377 size_t text_bytes;
2378 const char *text;
2379 enum XML_Error expected_error;
2380 };
2381
2382 const char prolog[] = "\0<\0?\0x\0m\0l\0"
2383 " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2384 " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0"
2385 "1\0"
2386 "6\0'"
2387 "\0?\0>\0\n"
2388 "\0<\0a\0>";
2389 struct CaseData cases[] = {
2390 {1, "\0", XML_ERROR_UNCLOSED_TOKEN},
2391 {2, "\0<", XML_ERROR_UNCLOSED_TOKEN},
2392 {3, "\0<\0", XML_ERROR_UNCLOSED_TOKEN},
2393 {4, "\0<\0!", XML_ERROR_UNCLOSED_TOKEN},
2394 {5, "\0<\0!\0", XML_ERROR_UNCLOSED_TOKEN},
2395 {6, "\0<\0!\0[", XML_ERROR_UNCLOSED_TOKEN},
2396 {7, "\0<\0!\0[\0", XML_ERROR_UNCLOSED_TOKEN},
2397 {8, "\0<\0!\0[\0C", XML_ERROR_UNCLOSED_TOKEN},
2398 {9, "\0<\0!\0[\0C\0", XML_ERROR_UNCLOSED_TOKEN},
2399 {10, "\0<\0!\0[\0C\0D", XML_ERROR_UNCLOSED_TOKEN},
2400 {11, "\0<\0!\0[\0C\0D\0", XML_ERROR_UNCLOSED_TOKEN},
2401 {12, "\0<\0!\0[\0C\0D\0A", XML_ERROR_UNCLOSED_TOKEN},
2402 {13, "\0<\0!\0[\0C\0D\0A\0", XML_ERROR_UNCLOSED_TOKEN},
2403 {14, "\0<\0!\0[\0C\0D\0A\0T", XML_ERROR_UNCLOSED_TOKEN},
2404 {15, "\0<\0!\0[\0C\0D\0A\0T\0", XML_ERROR_UNCLOSED_TOKEN},
2405 {16, "\0<\0!\0[\0C\0D\0A\0T\0A", XML_ERROR_UNCLOSED_TOKEN},
2406 {17, "\0<\0!\0[\0C\0D\0A\0T\0A\0", XML_ERROR_UNCLOSED_TOKEN},
2407 {18, "\0<\0!\0[\0C\0D\0A\0T\0A\0[", XML_ERROR_UNCLOSED_CDATA_SECTION},
2408 {19, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0", XML_ERROR_UNCLOSED_CDATA_SECTION},
2409 {20, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z", XML_ERROR_UNCLOSED_CDATA_SECTION},
2410 /* Now add a four-byte UTF-16 character */
2411 {21, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8",
2412 XML_ERROR_UNCLOSED_CDATA_SECTION},
2413 {22, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8\x34", XML_ERROR_PARTIAL_CHAR},
2414 {23, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8\x34\xdd",
2415 XML_ERROR_PARTIAL_CHAR},
2416 {24, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8\x34\xdd\x5e",
2417 XML_ERROR_UNCLOSED_CDATA_SECTION}};
2418 size_t i;
2419
2420 for (i = 0; i < sizeof(cases) / sizeof(struct CaseData); i++) {
2421 enum XML_Status actual_status;
2422 enum XML_Error actual_error;
2423
2424 if (_XML_Parse_SINGLE_BYTES(g_parser, prolog, (int)sizeof(prolog) - 1,
2425 XML_FALSE)
2426 == XML_STATUS_ERROR)
2427 xml_failure(g_parser);
2428 actual_status = _XML_Parse_SINGLE_BYTES(g_parser, cases[i].text,
2429 (int)cases[i].text_bytes, XML_TRUE);
2430 assert(actual_status == XML_STATUS_ERROR);
2431 actual_error = XML_GetErrorCode(g_parser);
2432 if (actual_error != cases[i].expected_error) {
2433 char message[1024];
2434
2435 sprintf(message,
2436 "Expected error %d (%" XML_FMT_STR "), got %d (%" XML_FMT_STR
2437 ") for case %lu\n",
2438 cases[i].expected_error, XML_ErrorString(cases[i].expected_error),
2439 actual_error, XML_ErrorString(actual_error),
2440 (long unsigned)(i + 1));
2441 fail(message);
2442 }
2443 XML_ParserReset(g_parser, NULL);
2444 }
2445 }
2446 END_TEST
2447 #endif /* ifndef XML_MIN_SIZE */
2448
2449 static const char *long_cdata_text
2450 = "<s><![CDATA["
2451 "012345678901234567890123456789012345678901234567890123456789"
2452 "012345678901234567890123456789012345678901234567890123456789"
2453 "012345678901234567890123456789012345678901234567890123456789"
2454 "012345678901234567890123456789012345678901234567890123456789"
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 "]]></s>";
2472
2473 /* Test stopping the parser in cdata handler */
START_TEST(test_stop_parser_between_cdata_calls)2474 START_TEST(test_stop_parser_between_cdata_calls) {
2475 const char *text = long_cdata_text;
2476
2477 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2478 resumable = XML_FALSE;
2479 expect_failure(text, XML_ERROR_ABORTED, "Parse not aborted in CDATA handler");
2480 }
2481 END_TEST
2482
2483 /* Test suspending the parser in cdata handler */
START_TEST(test_suspend_parser_between_cdata_calls)2484 START_TEST(test_suspend_parser_between_cdata_calls) {
2485 const char *text = long_cdata_text;
2486 enum XML_Status result;
2487
2488 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2489 resumable = XML_TRUE;
2490 result = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE);
2491 if (result != XML_STATUS_SUSPENDED) {
2492 if (result == XML_STATUS_ERROR)
2493 xml_failure(g_parser);
2494 fail("Parse not suspended in CDATA handler");
2495 }
2496 if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE)
2497 xml_failure(g_parser);
2498 }
2499 END_TEST
2500
2501 /* Test memory allocation functions */
START_TEST(test_memory_allocation)2502 START_TEST(test_memory_allocation) {
2503 char *buffer = (char *)XML_MemMalloc(g_parser, 256);
2504 char *p;
2505
2506 if (buffer == NULL) {
2507 fail("Allocation failed");
2508 } else {
2509 /* Try writing to memory; some OSes try to cheat! */
2510 buffer[0] = 'T';
2511 buffer[1] = 'E';
2512 buffer[2] = 'S';
2513 buffer[3] = 'T';
2514 buffer[4] = '\0';
2515 if (strcmp(buffer, "TEST") != 0) {
2516 fail("Memory not writable");
2517 } else {
2518 p = (char *)XML_MemRealloc(g_parser, buffer, 512);
2519 if (p == NULL) {
2520 fail("Reallocation failed");
2521 } else {
2522 /* Write again, just to be sure */
2523 buffer = p;
2524 buffer[0] = 'V';
2525 if (strcmp(buffer, "VEST") != 0) {
2526 fail("Reallocated memory not writable");
2527 }
2528 }
2529 }
2530 XML_MemFree(g_parser, buffer);
2531 }
2532 }
2533 END_TEST
2534
2535 static void XMLCALL
record_default_handler(void * userData,const XML_Char * s,int len)2536 record_default_handler(void *userData, const XML_Char *s, int len) {
2537 UNUSED_P(s);
2538 UNUSED_P(len);
2539 CharData_AppendXMLChars((CharData *)userData, XCS("D"), 1);
2540 }
2541
2542 static void XMLCALL
record_cdata_handler(void * userData,const XML_Char * s,int len)2543 record_cdata_handler(void *userData, const XML_Char *s, int len) {
2544 UNUSED_P(s);
2545 UNUSED_P(len);
2546 CharData_AppendXMLChars((CharData *)userData, XCS("C"), 1);
2547 XML_DefaultCurrent(g_parser);
2548 }
2549
2550 static void XMLCALL
record_cdata_nodefault_handler(void * userData,const XML_Char * s,int len)2551 record_cdata_nodefault_handler(void *userData, const XML_Char *s, int len) {
2552 UNUSED_P(s);
2553 UNUSED_P(len);
2554 CharData_AppendXMLChars((CharData *)userData, XCS("c"), 1);
2555 }
2556
2557 static void XMLCALL
record_skip_handler(void * userData,const XML_Char * entityName,int is_parameter_entity)2558 record_skip_handler(void *userData, const XML_Char *entityName,
2559 int is_parameter_entity) {
2560 UNUSED_P(entityName);
2561 CharData_AppendXMLChars((CharData *)userData,
2562 is_parameter_entity ? XCS("E") : XCS("e"), 1);
2563 }
2564
2565 /* Test XML_DefaultCurrent() passes handling on correctly */
START_TEST(test_default_current)2566 START_TEST(test_default_current) {
2567 const char *text = "<doc>hell]</doc>";
2568 const char *entity_text = "<!DOCTYPE doc [\n"
2569 "<!ENTITY entity '%'>\n"
2570 "]>\n"
2571 "<doc>&entity;</doc>";
2572 CharData storage;
2573
2574 XML_SetDefaultHandler(g_parser, record_default_handler);
2575 XML_SetCharacterDataHandler(g_parser, record_cdata_handler);
2576 CharData_Init(&storage);
2577 XML_SetUserData(g_parser, &storage);
2578 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2579 == XML_STATUS_ERROR)
2580 xml_failure(g_parser);
2581 CharData_CheckXMLChars(&storage, XCS("DCDCDCDCDCDD"));
2582
2583 /* Again, without the defaulting */
2584 XML_ParserReset(g_parser, NULL);
2585 XML_SetDefaultHandler(g_parser, record_default_handler);
2586 XML_SetCharacterDataHandler(g_parser, record_cdata_nodefault_handler);
2587 CharData_Init(&storage);
2588 XML_SetUserData(g_parser, &storage);
2589 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2590 == XML_STATUS_ERROR)
2591 xml_failure(g_parser);
2592 CharData_CheckXMLChars(&storage, XCS("DcccccD"));
2593
2594 /* Now with an internal entity to complicate matters */
2595 XML_ParserReset(g_parser, NULL);
2596 XML_SetDefaultHandler(g_parser, record_default_handler);
2597 XML_SetCharacterDataHandler(g_parser, record_cdata_handler);
2598 CharData_Init(&storage);
2599 XML_SetUserData(g_parser, &storage);
2600 if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text),
2601 XML_TRUE)
2602 == XML_STATUS_ERROR)
2603 xml_failure(g_parser);
2604 /* The default handler suppresses the entity */
2605 CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDDD"));
2606
2607 /* Again, with a skip handler */
2608 XML_ParserReset(g_parser, NULL);
2609 XML_SetDefaultHandler(g_parser, record_default_handler);
2610 XML_SetCharacterDataHandler(g_parser, record_cdata_handler);
2611 XML_SetSkippedEntityHandler(g_parser, record_skip_handler);
2612 CharData_Init(&storage);
2613 XML_SetUserData(g_parser, &storage);
2614 if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text),
2615 XML_TRUE)
2616 == XML_STATUS_ERROR)
2617 xml_failure(g_parser);
2618 /* The default handler suppresses the entity */
2619 CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDeD"));
2620
2621 /* This time, allow the entity through */
2622 XML_ParserReset(g_parser, NULL);
2623 XML_SetDefaultHandlerExpand(g_parser, record_default_handler);
2624 XML_SetCharacterDataHandler(g_parser, record_cdata_handler);
2625 CharData_Init(&storage);
2626 XML_SetUserData(g_parser, &storage);
2627 if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text),
2628 XML_TRUE)
2629 == XML_STATUS_ERROR)
2630 xml_failure(g_parser);
2631 CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDCDD"));
2632
2633 /* Finally, without passing the cdata to the default handler */
2634 XML_ParserReset(g_parser, NULL);
2635 XML_SetDefaultHandlerExpand(g_parser, record_default_handler);
2636 XML_SetCharacterDataHandler(g_parser, record_cdata_nodefault_handler);
2637 CharData_Init(&storage);
2638 XML_SetUserData(g_parser, &storage);
2639 if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text),
2640 XML_TRUE)
2641 == XML_STATUS_ERROR)
2642 xml_failure(g_parser);
2643 CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDcD"));
2644 }
2645 END_TEST
2646
2647 /* Test DTD element parsing code paths */
START_TEST(test_dtd_elements)2648 START_TEST(test_dtd_elements) {
2649 const char *text = "<!DOCTYPE doc [\n"
2650 "<!ELEMENT doc (chapter)>\n"
2651 "<!ELEMENT chapter (#PCDATA)>\n"
2652 "]>\n"
2653 "<doc><chapter>Wombats are go</chapter></doc>";
2654
2655 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
2656 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2657 == XML_STATUS_ERROR)
2658 xml_failure(g_parser);
2659 }
2660 END_TEST
2661
2662 /* Test foreign DTD handling */
START_TEST(test_set_foreign_dtd)2663 START_TEST(test_set_foreign_dtd) {
2664 const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n";
2665 const char *text2 = "<doc>&entity;</doc>";
2666 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
2667
2668 /* Check hash salt is passed through too */
2669 XML_SetHashSalt(g_parser, 0x12345678);
2670 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2671 XML_SetUserData(g_parser, &test_data);
2672 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
2673 /* Add a default handler to exercise more code paths */
2674 XML_SetDefaultHandler(g_parser, dummy_default_handler);
2675 if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE)
2676 fail("Could not set foreign DTD");
2677 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
2678 == XML_STATUS_ERROR)
2679 xml_failure(g_parser);
2680
2681 /* Ensure that trying to set the DTD after parsing has started
2682 * is faulted, even if it's the same setting.
2683 */
2684 if (XML_UseForeignDTD(g_parser, XML_TRUE)
2685 != XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING)
2686 fail("Failed to reject late foreign DTD setting");
2687 /* Ditto for the hash salt */
2688 if (XML_SetHashSalt(g_parser, 0x23456789))
2689 fail("Failed to reject late hash salt change");
2690
2691 /* Now finish the parse */
2692 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
2693 == XML_STATUS_ERROR)
2694 xml_failure(g_parser);
2695 }
2696 END_TEST
2697
2698 /* Test foreign DTD handling with a failing NotStandalone handler */
START_TEST(test_foreign_dtd_not_standalone)2699 START_TEST(test_foreign_dtd_not_standalone) {
2700 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
2701 "<doc>&entity;</doc>";
2702 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
2703
2704 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2705 XML_SetUserData(g_parser, &test_data);
2706 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
2707 XML_SetNotStandaloneHandler(g_parser, reject_not_standalone_handler);
2708 if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE)
2709 fail("Could not set foreign DTD");
2710 expect_failure(text, XML_ERROR_NOT_STANDALONE,
2711 "NotStandalonehandler failed to reject");
2712 }
2713 END_TEST
2714
2715 /* Test invalid character in a foreign DTD is faulted */
START_TEST(test_invalid_foreign_dtd)2716 START_TEST(test_invalid_foreign_dtd) {
2717 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
2718 "<doc>&entity;</doc>";
2719 ExtFaults test_data
2720 = {"$", "Dollar not faulted", NULL, XML_ERROR_INVALID_TOKEN};
2721
2722 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2723 XML_SetUserData(g_parser, &test_data);
2724 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
2725 XML_UseForeignDTD(g_parser, XML_TRUE);
2726 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
2727 "Bad DTD should not have been accepted");
2728 }
2729 END_TEST
2730
2731 /* Test foreign DTD use with a doctype */
START_TEST(test_foreign_dtd_with_doctype)2732 START_TEST(test_foreign_dtd_with_doctype) {
2733 const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n"
2734 "<!DOCTYPE doc [<!ENTITY entity 'hello world'>]>\n";
2735 const char *text2 = "<doc>&entity;</doc>";
2736 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
2737
2738 /* Check hash salt is passed through too */
2739 XML_SetHashSalt(g_parser, 0x12345678);
2740 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2741 XML_SetUserData(g_parser, &test_data);
2742 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
2743 /* Add a default handler to exercise more code paths */
2744 XML_SetDefaultHandler(g_parser, dummy_default_handler);
2745 if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE)
2746 fail("Could not set foreign DTD");
2747 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
2748 == XML_STATUS_ERROR)
2749 xml_failure(g_parser);
2750
2751 /* Ensure that trying to set the DTD after parsing has started
2752 * is faulted, even if it's the same setting.
2753 */
2754 if (XML_UseForeignDTD(g_parser, XML_TRUE)
2755 != XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING)
2756 fail("Failed to reject late foreign DTD setting");
2757 /* Ditto for the hash salt */
2758 if (XML_SetHashSalt(g_parser, 0x23456789))
2759 fail("Failed to reject late hash salt change");
2760
2761 /* Now finish the parse */
2762 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
2763 == XML_STATUS_ERROR)
2764 xml_failure(g_parser);
2765 }
2766 END_TEST
2767
2768 /* Test XML_UseForeignDTD with no external subset present */
2769 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)2770 external_entity_null_loader(XML_Parser parser, const XML_Char *context,
2771 const XML_Char *base, const XML_Char *systemId,
2772 const XML_Char *publicId) {
2773 UNUSED_P(parser);
2774 UNUSED_P(context);
2775 UNUSED_P(base);
2776 UNUSED_P(systemId);
2777 UNUSED_P(publicId);
2778 return XML_STATUS_OK;
2779 }
2780
START_TEST(test_foreign_dtd_without_external_subset)2781 START_TEST(test_foreign_dtd_without_external_subset) {
2782 const char *text = "<!DOCTYPE doc [<!ENTITY foo 'bar'>]>\n"
2783 "<doc>&foo;</doc>";
2784
2785 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2786 XML_SetUserData(g_parser, NULL);
2787 XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader);
2788 XML_UseForeignDTD(g_parser, XML_TRUE);
2789 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2790 == XML_STATUS_ERROR)
2791 xml_failure(g_parser);
2792 }
2793 END_TEST
2794
START_TEST(test_empty_foreign_dtd)2795 START_TEST(test_empty_foreign_dtd) {
2796 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
2797 "<doc>&entity;</doc>";
2798
2799 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2800 XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader);
2801 XML_UseForeignDTD(g_parser, XML_TRUE);
2802 expect_failure(text, XML_ERROR_UNDEFINED_ENTITY,
2803 "Undefined entity not faulted");
2804 }
2805 END_TEST
2806
2807 /* Test XML Base is set and unset appropriately */
START_TEST(test_set_base)2808 START_TEST(test_set_base) {
2809 const XML_Char *old_base;
2810 const XML_Char *new_base = XCS("/local/file/name.xml");
2811
2812 old_base = XML_GetBase(g_parser);
2813 if (XML_SetBase(g_parser, new_base) != XML_STATUS_OK)
2814 fail("Unable to set base");
2815 if (xcstrcmp(XML_GetBase(g_parser), new_base) != 0)
2816 fail("Base setting not correct");
2817 if (XML_SetBase(g_parser, NULL) != XML_STATUS_OK)
2818 fail("Unable to NULL base");
2819 if (XML_GetBase(g_parser) != NULL)
2820 fail("Base setting not nulled");
2821 XML_SetBase(g_parser, old_base);
2822 }
2823 END_TEST
2824
2825 /* Test attribute counts, indexing, etc */
2826 typedef struct attrInfo {
2827 const XML_Char *name;
2828 const XML_Char *value;
2829 } AttrInfo;
2830
2831 typedef struct elementInfo {
2832 const XML_Char *name;
2833 int attr_count;
2834 const XML_Char *id_name;
2835 AttrInfo *attributes;
2836 } ElementInfo;
2837
2838 static void XMLCALL
counting_start_element_handler(void * userData,const XML_Char * name,const XML_Char ** atts)2839 counting_start_element_handler(void *userData, const XML_Char *name,
2840 const XML_Char **atts) {
2841 ElementInfo *info = (ElementInfo *)userData;
2842 AttrInfo *attr;
2843 int count, id, i;
2844
2845 while (info->name != NULL) {
2846 if (! xcstrcmp(name, info->name))
2847 break;
2848 info++;
2849 }
2850 if (info->name == NULL)
2851 fail("Element not recognised");
2852 /* The attribute count is twice what you might expect. It is a
2853 * count of items in atts, an array which contains alternating
2854 * attribute names and attribute values. For the naive user this
2855 * is possibly a little unexpected, but it is what the
2856 * documentation in expat.h tells us to expect.
2857 */
2858 count = XML_GetSpecifiedAttributeCount(g_parser);
2859 if (info->attr_count * 2 != count) {
2860 fail("Not got expected attribute count");
2861 return;
2862 }
2863 id = XML_GetIdAttributeIndex(g_parser);
2864 if (id == -1 && info->id_name != NULL) {
2865 fail("ID not present");
2866 return;
2867 }
2868 if (id != -1 && xcstrcmp(atts[id], info->id_name)) {
2869 fail("ID does not have the correct name");
2870 return;
2871 }
2872 for (i = 0; i < info->attr_count; i++) {
2873 attr = info->attributes;
2874 while (attr->name != NULL) {
2875 if (! xcstrcmp(atts[0], attr->name))
2876 break;
2877 attr++;
2878 }
2879 if (attr->name == NULL) {
2880 fail("Attribute not recognised");
2881 return;
2882 }
2883 if (xcstrcmp(atts[1], attr->value)) {
2884 fail("Attribute has wrong value");
2885 return;
2886 }
2887 /* Remember, two entries in atts per attribute (see above) */
2888 atts += 2;
2889 }
2890 }
2891
START_TEST(test_attributes)2892 START_TEST(test_attributes) {
2893 const char *text = "<!DOCTYPE doc [\n"
2894 "<!ELEMENT doc (tag)>\n"
2895 "<!ATTLIST doc id ID #REQUIRED>\n"
2896 "]>"
2897 "<doc a='1' id='one' b='2'>"
2898 "<tag c='3'/>"
2899 "</doc>";
2900 AttrInfo doc_info[] = {{XCS("a"), XCS("1")},
2901 {XCS("b"), XCS("2")},
2902 {XCS("id"), XCS("one")},
2903 {NULL, NULL}};
2904 AttrInfo tag_info[] = {{XCS("c"), XCS("3")}, {NULL, NULL}};
2905 ElementInfo info[] = {{XCS("doc"), 3, XCS("id"), NULL},
2906 {XCS("tag"), 1, NULL, NULL},
2907 {NULL, 0, NULL, NULL}};
2908 info[0].attributes = doc_info;
2909 info[1].attributes = tag_info;
2910
2911 XML_SetStartElementHandler(g_parser, counting_start_element_handler);
2912 XML_SetUserData(g_parser, info);
2913 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2914 == XML_STATUS_ERROR)
2915 xml_failure(g_parser);
2916 }
2917 END_TEST
2918
2919 /* Test reset works correctly in the middle of processing an internal
2920 * entity. Exercises some obscure code in XML_ParserReset().
2921 */
START_TEST(test_reset_in_entity)2922 START_TEST(test_reset_in_entity) {
2923 const char *text = "<!DOCTYPE doc [\n"
2924 "<!ENTITY wombat 'wom'>\n"
2925 "<!ENTITY entity 'hi &wom; there'>\n"
2926 "]>\n"
2927 "<doc>&entity;</doc>";
2928 XML_ParsingStatus status;
2929
2930 resumable = XML_TRUE;
2931 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2932 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
2933 == XML_STATUS_ERROR)
2934 xml_failure(g_parser);
2935 XML_GetParsingStatus(g_parser, &status);
2936 if (status.parsing != XML_SUSPENDED)
2937 fail("Parsing status not SUSPENDED");
2938 XML_ParserReset(g_parser, NULL);
2939 XML_GetParsingStatus(g_parser, &status);
2940 if (status.parsing != XML_INITIALIZED)
2941 fail("Parsing status doesn't reset to INITIALIZED");
2942 }
2943 END_TEST
2944
2945 /* Test that resume correctly passes through parse errors */
START_TEST(test_resume_invalid_parse)2946 START_TEST(test_resume_invalid_parse) {
2947 const char *text = "<doc>Hello</doc"; /* Missing closing wedge */
2948
2949 resumable = XML_TRUE;
2950 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2951 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
2952 == XML_STATUS_ERROR)
2953 xml_failure(g_parser);
2954 if (XML_ResumeParser(g_parser) == XML_STATUS_OK)
2955 fail("Resumed invalid parse not faulted");
2956 if (XML_GetErrorCode(g_parser) != XML_ERROR_UNCLOSED_TOKEN)
2957 fail("Invalid parse not correctly faulted");
2958 }
2959 END_TEST
2960
2961 /* Test that re-suspended parses are correctly passed through */
START_TEST(test_resume_resuspended)2962 START_TEST(test_resume_resuspended) {
2963 const char *text = "<doc>Hello<meep/>world</doc>";
2964
2965 resumable = XML_TRUE;
2966 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2967 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
2968 == XML_STATUS_ERROR)
2969 xml_failure(g_parser);
2970 resumable = XML_TRUE;
2971 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2972 if (XML_ResumeParser(g_parser) != XML_STATUS_SUSPENDED)
2973 fail("Resumption not suspended");
2974 /* This one should succeed and finish up */
2975 if (XML_ResumeParser(g_parser) != XML_STATUS_OK)
2976 xml_failure(g_parser);
2977 }
2978 END_TEST
2979
2980 /* Test that CDATA shows up correctly through a default handler */
START_TEST(test_cdata_default)2981 START_TEST(test_cdata_default) {
2982 const char *text = "<doc><![CDATA[Hello\nworld]]></doc>";
2983 const XML_Char *expected = XCS("<doc><![CDATA[Hello\nworld]]></doc>");
2984 CharData storage;
2985
2986 CharData_Init(&storage);
2987 XML_SetUserData(g_parser, &storage);
2988 XML_SetDefaultHandler(g_parser, accumulate_characters);
2989
2990 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2991 == XML_STATUS_ERROR)
2992 xml_failure(g_parser);
2993 CharData_CheckXMLChars(&storage, expected);
2994 }
2995 END_TEST
2996
2997 /* Test resetting a subordinate parser does exactly nothing */
2998 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)2999 external_entity_resetter(XML_Parser parser, const XML_Char *context,
3000 const XML_Char *base, const XML_Char *systemId,
3001 const XML_Char *publicId) {
3002 const char *text = "<!ELEMENT doc (#PCDATA)*>";
3003 XML_Parser ext_parser;
3004 XML_ParsingStatus status;
3005
3006 UNUSED_P(base);
3007 UNUSED_P(systemId);
3008 UNUSED_P(publicId);
3009 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3010 if (ext_parser == NULL)
3011 fail("Could not create external entity parser");
3012 XML_GetParsingStatus(ext_parser, &status);
3013 if (status.parsing != XML_INITIALIZED) {
3014 fail("Parsing status is not INITIALIZED");
3015 return XML_STATUS_ERROR;
3016 }
3017 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3018 == XML_STATUS_ERROR) {
3019 xml_failure(parser);
3020 return XML_STATUS_ERROR;
3021 }
3022 XML_GetParsingStatus(ext_parser, &status);
3023 if (status.parsing != XML_FINISHED) {
3024 fail("Parsing status is not FINISHED");
3025 return XML_STATUS_ERROR;
3026 }
3027 /* Check we can't parse here */
3028 if (XML_Parse(ext_parser, text, (int)strlen(text), XML_TRUE)
3029 != XML_STATUS_ERROR)
3030 fail("Parsing when finished not faulted");
3031 if (XML_GetErrorCode(ext_parser) != XML_ERROR_FINISHED)
3032 fail("Parsing when finished faulted with wrong code");
3033 XML_ParserReset(ext_parser, NULL);
3034 XML_GetParsingStatus(ext_parser, &status);
3035 if (status.parsing != XML_FINISHED) {
3036 fail("Parsing status not still FINISHED");
3037 return XML_STATUS_ERROR;
3038 }
3039 XML_ParserFree(ext_parser);
3040 return XML_STATUS_OK;
3041 }
3042
START_TEST(test_subordinate_reset)3043 START_TEST(test_subordinate_reset) {
3044 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
3045 "<!DOCTYPE doc SYSTEM 'foo'>\n"
3046 "<doc>&entity;</doc>";
3047
3048 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3049 XML_SetExternalEntityRefHandler(g_parser, external_entity_resetter);
3050 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3051 == XML_STATUS_ERROR)
3052 xml_failure(g_parser);
3053 }
3054 END_TEST
3055
3056 /* Test suspending a subordinate parser */
3057
3058 static void XMLCALL
entity_suspending_decl_handler(void * userData,const XML_Char * name,XML_Content * model)3059 entity_suspending_decl_handler(void *userData, const XML_Char *name,
3060 XML_Content *model) {
3061 XML_Parser ext_parser = (XML_Parser)userData;
3062
3063 UNUSED_P(name);
3064 if (XML_StopParser(ext_parser, XML_TRUE) != XML_STATUS_ERROR)
3065 fail("Attempting to suspend a subordinate parser not faulted");
3066 if (XML_GetErrorCode(ext_parser) != XML_ERROR_SUSPEND_PE)
3067 fail("Suspending subordinate parser get wrong code");
3068 XML_SetElementDeclHandler(ext_parser, NULL);
3069 XML_FreeContentModel(g_parser, model);
3070 }
3071
3072 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)3073 external_entity_suspender(XML_Parser parser, const XML_Char *context,
3074 const XML_Char *base, const XML_Char *systemId,
3075 const XML_Char *publicId) {
3076 const char *text = "<!ELEMENT doc (#PCDATA)*>";
3077 XML_Parser ext_parser;
3078
3079 UNUSED_P(base);
3080 UNUSED_P(systemId);
3081 UNUSED_P(publicId);
3082 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3083 if (ext_parser == NULL)
3084 fail("Could not create external entity parser");
3085 XML_SetElementDeclHandler(ext_parser, entity_suspending_decl_handler);
3086 XML_SetUserData(ext_parser, ext_parser);
3087 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3088 == XML_STATUS_ERROR) {
3089 xml_failure(ext_parser);
3090 return XML_STATUS_ERROR;
3091 }
3092 XML_ParserFree(ext_parser);
3093 return XML_STATUS_OK;
3094 }
3095
START_TEST(test_subordinate_suspend)3096 START_TEST(test_subordinate_suspend) {
3097 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
3098 "<!DOCTYPE doc SYSTEM 'foo'>\n"
3099 "<doc>&entity;</doc>";
3100
3101 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3102 XML_SetExternalEntityRefHandler(g_parser, external_entity_suspender);
3103 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3104 == XML_STATUS_ERROR)
3105 xml_failure(g_parser);
3106 }
3107 END_TEST
3108
3109 /* Test suspending a subordinate parser from an XML declaration */
3110 /* Increases code coverage of the tests */
3111 static void XMLCALL
entity_suspending_xdecl_handler(void * userData,const XML_Char * version,const XML_Char * encoding,int standalone)3112 entity_suspending_xdecl_handler(void *userData, const XML_Char *version,
3113 const XML_Char *encoding, int standalone) {
3114 XML_Parser ext_parser = (XML_Parser)userData;
3115
3116 UNUSED_P(version);
3117 UNUSED_P(encoding);
3118 UNUSED_P(standalone);
3119 XML_StopParser(ext_parser, resumable);
3120 XML_SetXmlDeclHandler(ext_parser, NULL);
3121 }
3122
3123 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)3124 external_entity_suspend_xmldecl(XML_Parser parser, const XML_Char *context,
3125 const XML_Char *base, const XML_Char *systemId,
3126 const XML_Char *publicId) {
3127 const char *text = "<?xml version='1.0' encoding='us-ascii'?>";
3128 XML_Parser ext_parser;
3129 XML_ParsingStatus status;
3130 enum XML_Status rc;
3131
3132 UNUSED_P(base);
3133 UNUSED_P(systemId);
3134 UNUSED_P(publicId);
3135 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3136 if (ext_parser == NULL)
3137 fail("Could not create external entity parser");
3138 XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
3139 XML_SetUserData(ext_parser, ext_parser);
3140 rc = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
3141 XML_GetParsingStatus(ext_parser, &status);
3142 if (resumable) {
3143 if (rc == XML_STATUS_ERROR)
3144 xml_failure(ext_parser);
3145 if (status.parsing != XML_SUSPENDED)
3146 fail("Ext Parsing status not SUSPENDED");
3147 } else {
3148 if (rc != XML_STATUS_ERROR)
3149 fail("Ext parsing not aborted");
3150 if (XML_GetErrorCode(ext_parser) != XML_ERROR_ABORTED)
3151 xml_failure(ext_parser);
3152 if (status.parsing != XML_FINISHED)
3153 fail("Ext Parsing status not FINISHED");
3154 }
3155
3156 XML_ParserFree(ext_parser);
3157 return XML_STATUS_OK;
3158 }
3159
START_TEST(test_subordinate_xdecl_suspend)3160 START_TEST(test_subordinate_xdecl_suspend) {
3161 const char *text
3162 = "<!DOCTYPE doc [\n"
3163 " <!ENTITY entity SYSTEM 'http://example.org/dummy.ent'>\n"
3164 "]>\n"
3165 "<doc>&entity;</doc>";
3166
3167 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3168 XML_SetExternalEntityRefHandler(g_parser, external_entity_suspend_xmldecl);
3169 resumable = XML_TRUE;
3170 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3171 == XML_STATUS_ERROR)
3172 xml_failure(g_parser);
3173 }
3174 END_TEST
3175
START_TEST(test_subordinate_xdecl_abort)3176 START_TEST(test_subordinate_xdecl_abort) {
3177 const char *text
3178 = "<!DOCTYPE doc [\n"
3179 " <!ENTITY entity SYSTEM 'http://example.org/dummy.ent'>\n"
3180 "]>\n"
3181 "<doc>&entity;</doc>";
3182
3183 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3184 XML_SetExternalEntityRefHandler(g_parser, external_entity_suspend_xmldecl);
3185 resumable = XML_FALSE;
3186 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3187 == XML_STATUS_ERROR)
3188 xml_failure(g_parser);
3189 }
3190 END_TEST
3191
3192 /* Test external entity fault handling with suspension */
3193 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)3194 external_entity_suspending_faulter(XML_Parser parser, const XML_Char *context,
3195 const XML_Char *base,
3196 const XML_Char *systemId,
3197 const XML_Char *publicId) {
3198 XML_Parser ext_parser;
3199 ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser);
3200 void *buffer;
3201 int parse_len = (int)strlen(fault->parse_text);
3202
3203 UNUSED_P(base);
3204 UNUSED_P(systemId);
3205 UNUSED_P(publicId);
3206 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3207 if (ext_parser == NULL)
3208 fail("Could not create external entity parser");
3209 XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
3210 XML_SetUserData(ext_parser, ext_parser);
3211 resumable = XML_TRUE;
3212 buffer = XML_GetBuffer(ext_parser, parse_len);
3213 if (buffer == NULL)
3214 fail("Could not allocate parse buffer");
3215 assert(buffer != NULL);
3216 memcpy(buffer, fault->parse_text, parse_len);
3217 if (XML_ParseBuffer(ext_parser, parse_len, XML_FALSE) != XML_STATUS_SUSPENDED)
3218 fail("XML declaration did not suspend");
3219 if (XML_ResumeParser(ext_parser) != XML_STATUS_OK)
3220 xml_failure(ext_parser);
3221 if (XML_ParseBuffer(ext_parser, 0, XML_TRUE) != XML_STATUS_ERROR)
3222 fail(fault->fail_text);
3223 if (XML_GetErrorCode(ext_parser) != fault->error)
3224 xml_failure(ext_parser);
3225
3226 XML_ParserFree(ext_parser);
3227 return XML_STATUS_ERROR;
3228 }
3229
START_TEST(test_ext_entity_invalid_suspended_parse)3230 START_TEST(test_ext_entity_invalid_suspended_parse) {
3231 const char *text = "<!DOCTYPE doc [\n"
3232 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
3233 "]>\n"
3234 "<doc>&en;</doc>";
3235 ExtFaults faults[]
3236 = {{"<?xml version='1.0' encoding='us-ascii'?><",
3237 "Incomplete element declaration not faulted", NULL,
3238 XML_ERROR_UNCLOSED_TOKEN},
3239 {/* First two bytes of a three-byte char */
3240 "<?xml version='1.0' encoding='utf-8'?>\xe2\x82",
3241 "Incomplete character not faulted", NULL, XML_ERROR_PARTIAL_CHAR},
3242 {NULL, NULL, NULL, XML_ERROR_NONE}};
3243 ExtFaults *fault;
3244
3245 for (fault = &faults[0]; fault->parse_text != NULL; fault++) {
3246 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3247 XML_SetExternalEntityRefHandler(g_parser,
3248 external_entity_suspending_faulter);
3249 XML_SetUserData(g_parser, fault);
3250 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
3251 "Parser did not report external entity error");
3252 XML_ParserReset(g_parser, NULL);
3253 }
3254 }
3255 END_TEST
3256
3257 /* Test setting an explicit encoding */
START_TEST(test_explicit_encoding)3258 START_TEST(test_explicit_encoding) {
3259 const char *text1 = "<doc>Hello ";
3260 const char *text2 = " World</doc>";
3261
3262 /* Just check that we can set the encoding to NULL before starting */
3263 if (XML_SetEncoding(g_parser, NULL) != XML_STATUS_OK)
3264 fail("Failed to initialise encoding to NULL");
3265 /* Say we are UTF-8 */
3266 if (XML_SetEncoding(g_parser, XCS("utf-8")) != XML_STATUS_OK)
3267 fail("Failed to set explicit encoding");
3268 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
3269 == XML_STATUS_ERROR)
3270 xml_failure(g_parser);
3271 /* Try to switch encodings mid-parse */
3272 if (XML_SetEncoding(g_parser, XCS("us-ascii")) != XML_STATUS_ERROR)
3273 fail("Allowed encoding change");
3274 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
3275 == XML_STATUS_ERROR)
3276 xml_failure(g_parser);
3277 /* Try now the parse is over */
3278 if (XML_SetEncoding(g_parser, NULL) != XML_STATUS_OK)
3279 fail("Failed to unset encoding");
3280 }
3281 END_TEST
3282
3283 /* Test handling of trailing CR (rather than newline) */
3284 static void XMLCALL
cr_cdata_handler(void * userData,const XML_Char * s,int len)3285 cr_cdata_handler(void *userData, const XML_Char *s, int len) {
3286 int *pfound = (int *)userData;
3287
3288 /* Internal processing turns the CR into a newline for the
3289 * character data handler, but not for the default handler
3290 */
3291 if (len == 1 && (*s == XCS('\n') || *s == XCS('\r')))
3292 *pfound = 1;
3293 }
3294
START_TEST(test_trailing_cr)3295 START_TEST(test_trailing_cr) {
3296 const char *text = "<doc>\r";
3297 int found_cr;
3298
3299 /* Try with a character handler, for code coverage */
3300 XML_SetCharacterDataHandler(g_parser, cr_cdata_handler);
3301 XML_SetUserData(g_parser, &found_cr);
3302 found_cr = 0;
3303 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3304 == XML_STATUS_OK)
3305 fail("Failed to fault unclosed doc");
3306 if (found_cr == 0)
3307 fail("Did not catch the carriage return");
3308 XML_ParserReset(g_parser, NULL);
3309
3310 /* Now with a default handler instead */
3311 XML_SetDefaultHandler(g_parser, cr_cdata_handler);
3312 XML_SetUserData(g_parser, &found_cr);
3313 found_cr = 0;
3314 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3315 == XML_STATUS_OK)
3316 fail("Failed to fault unclosed doc");
3317 if (found_cr == 0)
3318 fail("Did not catch default carriage return");
3319 }
3320 END_TEST
3321
3322 /* Test trailing CR in an external entity parse */
3323 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)3324 external_entity_cr_catcher(XML_Parser parser, const XML_Char *context,
3325 const XML_Char *base, const XML_Char *systemId,
3326 const XML_Char *publicId) {
3327 const char *text = "\r";
3328 XML_Parser ext_parser;
3329
3330 UNUSED_P(base);
3331 UNUSED_P(systemId);
3332 UNUSED_P(publicId);
3333 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3334 if (ext_parser == NULL)
3335 fail("Could not create external entity parser");
3336 XML_SetCharacterDataHandler(ext_parser, cr_cdata_handler);
3337 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3338 == XML_STATUS_ERROR)
3339 xml_failure(ext_parser);
3340 XML_ParserFree(ext_parser);
3341 return XML_STATUS_OK;
3342 }
3343
3344 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)3345 external_entity_bad_cr_catcher(XML_Parser parser, const XML_Char *context,
3346 const XML_Char *base, const XML_Char *systemId,
3347 const XML_Char *publicId) {
3348 const char *text = "<tag>\r";
3349 XML_Parser ext_parser;
3350
3351 UNUSED_P(base);
3352 UNUSED_P(systemId);
3353 UNUSED_P(publicId);
3354 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3355 if (ext_parser == NULL)
3356 fail("Could not create external entity parser");
3357 XML_SetCharacterDataHandler(ext_parser, cr_cdata_handler);
3358 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3359 == XML_STATUS_OK)
3360 fail("Async entity error not caught");
3361 if (XML_GetErrorCode(ext_parser) != XML_ERROR_ASYNC_ENTITY)
3362 xml_failure(ext_parser);
3363 XML_ParserFree(ext_parser);
3364 return XML_STATUS_OK;
3365 }
3366
START_TEST(test_ext_entity_trailing_cr)3367 START_TEST(test_ext_entity_trailing_cr) {
3368 const char *text = "<!DOCTYPE doc [\n"
3369 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
3370 "]>\n"
3371 "<doc>&en;</doc>";
3372 int found_cr;
3373
3374 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3375 XML_SetExternalEntityRefHandler(g_parser, external_entity_cr_catcher);
3376 XML_SetUserData(g_parser, &found_cr);
3377 found_cr = 0;
3378 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3379 != XML_STATUS_OK)
3380 xml_failure(g_parser);
3381 if (found_cr == 0)
3382 fail("No carriage return found");
3383 XML_ParserReset(g_parser, NULL);
3384
3385 /* Try again with a different trailing CR */
3386 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3387 XML_SetExternalEntityRefHandler(g_parser, external_entity_bad_cr_catcher);
3388 XML_SetUserData(g_parser, &found_cr);
3389 found_cr = 0;
3390 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3391 != XML_STATUS_OK)
3392 xml_failure(g_parser);
3393 if (found_cr == 0)
3394 fail("No carriage return found");
3395 }
3396 END_TEST
3397
3398 /* Test handling of trailing square bracket */
3399 static void XMLCALL
rsqb_handler(void * userData,const XML_Char * s,int len)3400 rsqb_handler(void *userData, const XML_Char *s, int len) {
3401 int *pfound = (int *)userData;
3402
3403 if (len == 1 && *s == XCS(']'))
3404 *pfound = 1;
3405 }
3406
START_TEST(test_trailing_rsqb)3407 START_TEST(test_trailing_rsqb) {
3408 const char *text8 = "<doc>]";
3409 const char text16[] = "\xFF\xFE<\000d\000o\000c\000>\000]\000";
3410 int found_rsqb;
3411 int text8_len = (int)strlen(text8);
3412
3413 XML_SetCharacterDataHandler(g_parser, rsqb_handler);
3414 XML_SetUserData(g_parser, &found_rsqb);
3415 found_rsqb = 0;
3416 if (_XML_Parse_SINGLE_BYTES(g_parser, text8, text8_len, XML_TRUE)
3417 == XML_STATUS_OK)
3418 fail("Failed to fault unclosed doc");
3419 if (found_rsqb == 0)
3420 fail("Did not catch the right square bracket");
3421
3422 /* Try again with a different encoding */
3423 XML_ParserReset(g_parser, NULL);
3424 XML_SetCharacterDataHandler(g_parser, rsqb_handler);
3425 XML_SetUserData(g_parser, &found_rsqb);
3426 found_rsqb = 0;
3427 if (_XML_Parse_SINGLE_BYTES(g_parser, text16, (int)sizeof(text16) - 1,
3428 XML_TRUE)
3429 == XML_STATUS_OK)
3430 fail("Failed to fault unclosed doc");
3431 if (found_rsqb == 0)
3432 fail("Did not catch the right square bracket");
3433
3434 /* And finally with a default handler */
3435 XML_ParserReset(g_parser, NULL);
3436 XML_SetDefaultHandler(g_parser, rsqb_handler);
3437 XML_SetUserData(g_parser, &found_rsqb);
3438 found_rsqb = 0;
3439 if (_XML_Parse_SINGLE_BYTES(g_parser, text16, (int)sizeof(text16) - 1,
3440 XML_TRUE)
3441 == XML_STATUS_OK)
3442 fail("Failed to fault unclosed doc");
3443 if (found_rsqb == 0)
3444 fail("Did not catch the right square bracket");
3445 }
3446 END_TEST
3447
3448 /* Test trailing right square bracket in an external entity parse */
3449 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)3450 external_entity_rsqb_catcher(XML_Parser parser, const XML_Char *context,
3451 const XML_Char *base, const XML_Char *systemId,
3452 const XML_Char *publicId) {
3453 const char *text = "<tag>]";
3454 XML_Parser ext_parser;
3455
3456 UNUSED_P(base);
3457 UNUSED_P(systemId);
3458 UNUSED_P(publicId);
3459 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3460 if (ext_parser == NULL)
3461 fail("Could not create external entity parser");
3462 XML_SetCharacterDataHandler(ext_parser, rsqb_handler);
3463 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3464 != XML_STATUS_ERROR)
3465 fail("Async entity error not caught");
3466 if (XML_GetErrorCode(ext_parser) != XML_ERROR_ASYNC_ENTITY)
3467 xml_failure(ext_parser);
3468 XML_ParserFree(ext_parser);
3469 return XML_STATUS_OK;
3470 }
3471
START_TEST(test_ext_entity_trailing_rsqb)3472 START_TEST(test_ext_entity_trailing_rsqb) {
3473 const char *text = "<!DOCTYPE doc [\n"
3474 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
3475 "]>\n"
3476 "<doc>&en;</doc>";
3477 int found_rsqb;
3478
3479 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3480 XML_SetExternalEntityRefHandler(g_parser, external_entity_rsqb_catcher);
3481 XML_SetUserData(g_parser, &found_rsqb);
3482 found_rsqb = 0;
3483 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3484 != XML_STATUS_OK)
3485 xml_failure(g_parser);
3486 if (found_rsqb == 0)
3487 fail("No right square bracket found");
3488 }
3489 END_TEST
3490
3491 /* Test CDATA handling in an external entity */
3492 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)3493 external_entity_good_cdata_ascii(XML_Parser parser, const XML_Char *context,
3494 const XML_Char *base, const XML_Char *systemId,
3495 const XML_Char *publicId) {
3496 const char *text = "<a><![CDATA[<greeting>Hello, world!</greeting>]]></a>";
3497 const XML_Char *expected = XCS("<greeting>Hello, world!</greeting>");
3498 CharData storage;
3499 XML_Parser ext_parser;
3500
3501 UNUSED_P(base);
3502 UNUSED_P(systemId);
3503 UNUSED_P(publicId);
3504 CharData_Init(&storage);
3505 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3506 if (ext_parser == NULL)
3507 fail("Could not create external entity parser");
3508 XML_SetUserData(ext_parser, &storage);
3509 XML_SetCharacterDataHandler(ext_parser, accumulate_characters);
3510
3511 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3512 == XML_STATUS_ERROR)
3513 xml_failure(ext_parser);
3514 CharData_CheckXMLChars(&storage, expected);
3515
3516 XML_ParserFree(ext_parser);
3517 return XML_STATUS_OK;
3518 }
3519
START_TEST(test_ext_entity_good_cdata)3520 START_TEST(test_ext_entity_good_cdata) {
3521 const char *text = "<!DOCTYPE doc [\n"
3522 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
3523 "]>\n"
3524 "<doc>&en;</doc>";
3525
3526 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3527 XML_SetExternalEntityRefHandler(g_parser, external_entity_good_cdata_ascii);
3528 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3529 != XML_STATUS_OK)
3530 xml_failure(g_parser);
3531 }
3532 END_TEST
3533
3534 /* Test user parameter settings */
3535 /* Variable holding the expected handler userData */
3536 static void *handler_data = NULL;
3537 /* Count of the number of times the comment handler has been invoked */
3538 static int comment_count = 0;
3539 /* Count of the number of skipped entities */
3540 static int skip_count = 0;
3541 /* Count of the number of times the XML declaration handler is invoked */
3542 static int xdecl_count = 0;
3543
3544 static void XMLCALL
xml_decl_handler(void * userData,const XML_Char * version,const XML_Char * encoding,int standalone)3545 xml_decl_handler(void *userData, const XML_Char *version,
3546 const XML_Char *encoding, int standalone) {
3547 UNUSED_P(version);
3548 UNUSED_P(encoding);
3549 if (userData != handler_data)
3550 fail("User data (xml decl) not correctly set");
3551 if (standalone != -1)
3552 fail("Standalone not flagged as not present in XML decl");
3553 xdecl_count++;
3554 }
3555
3556 static void XMLCALL
param_check_skip_handler(void * userData,const XML_Char * entityName,int is_parameter_entity)3557 param_check_skip_handler(void *userData, const XML_Char *entityName,
3558 int is_parameter_entity) {
3559 UNUSED_P(entityName);
3560 UNUSED_P(is_parameter_entity);
3561 if (userData != handler_data)
3562 fail("User data (skip) not correctly set");
3563 skip_count++;
3564 }
3565
3566 static void XMLCALL
data_check_comment_handler(void * userData,const XML_Char * data)3567 data_check_comment_handler(void *userData, const XML_Char *data) {
3568 UNUSED_P(data);
3569 /* Check that the userData passed through is what we expect */
3570 if (userData != handler_data)
3571 fail("User data (parser) not correctly set");
3572 /* Check that the user data in the parser is appropriate */
3573 if (XML_GetUserData(userData) != (void *)1)
3574 fail("User data in parser not correctly set");
3575 comment_count++;
3576 }
3577
3578 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)3579 external_entity_param_checker(XML_Parser parser, const XML_Char *context,
3580 const XML_Char *base, const XML_Char *systemId,
3581 const XML_Char *publicId) {
3582 const char *text = "<!-- Subordinate parser -->\n"
3583 "<!ELEMENT doc (#PCDATA)*>";
3584 XML_Parser ext_parser;
3585
3586 UNUSED_P(base);
3587 UNUSED_P(systemId);
3588 UNUSED_P(publicId);
3589 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3590 if (ext_parser == NULL)
3591 fail("Could not create external entity parser");
3592 handler_data = ext_parser;
3593 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3594 == XML_STATUS_ERROR) {
3595 xml_failure(parser);
3596 return XML_STATUS_ERROR;
3597 }
3598 handler_data = parser;
3599 XML_ParserFree(ext_parser);
3600 return XML_STATUS_OK;
3601 }
3602
START_TEST(test_user_parameters)3603 START_TEST(test_user_parameters) {
3604 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
3605 "<!-- Primary parse -->\n"
3606 "<!DOCTYPE doc SYSTEM 'foo'>\n"
3607 "<doc>&entity;";
3608 const char *epilog = "<!-- Back to primary parser -->\n"
3609 "</doc>";
3610
3611 comment_count = 0;
3612 skip_count = 0;
3613 xdecl_count = 0;
3614 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3615 XML_SetXmlDeclHandler(g_parser, xml_decl_handler);
3616 XML_SetExternalEntityRefHandler(g_parser, external_entity_param_checker);
3617 XML_SetCommentHandler(g_parser, data_check_comment_handler);
3618 XML_SetSkippedEntityHandler(g_parser, param_check_skip_handler);
3619 XML_UseParserAsHandlerArg(g_parser);
3620 XML_SetUserData(g_parser, (void *)1);
3621 handler_data = g_parser;
3622 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
3623 == XML_STATUS_ERROR)
3624 xml_failure(g_parser);
3625 if (comment_count != 2)
3626 fail("Comment handler not invoked enough times");
3627 /* Ensure we can't change policy mid-parse */
3628 if (XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_NEVER))
3629 fail("Changed param entity parsing policy while parsing");
3630 if (_XML_Parse_SINGLE_BYTES(g_parser, epilog, (int)strlen(epilog), XML_TRUE)
3631 == XML_STATUS_ERROR)
3632 xml_failure(g_parser);
3633 if (comment_count != 3)
3634 fail("Comment handler not invoked enough times");
3635 if (skip_count != 1)
3636 fail("Skip handler not invoked enough times");
3637 if (xdecl_count != 1)
3638 fail("XML declaration handler not invoked");
3639 }
3640 END_TEST
3641
3642 /* Test that an explicit external entity handler argument replaces
3643 * the parser as the first argument.
3644 *
3645 * We do not call the first parameter to the external entity handler
3646 * 'parser' for once, since the first time the handler is called it
3647 * will actually be a text string. We need to be able to access the
3648 * global 'parser' variable to create our external entity parser from,
3649 * since there are code paths we need to ensure get executed.
3650 */
3651 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)3652 external_entity_ref_param_checker(XML_Parser parameter, const XML_Char *context,
3653 const XML_Char *base,
3654 const XML_Char *systemId,
3655 const XML_Char *publicId) {
3656 const char *text = "<!ELEMENT doc (#PCDATA)*>";
3657 XML_Parser ext_parser;
3658
3659 UNUSED_P(base);
3660 UNUSED_P(systemId);
3661 UNUSED_P(publicId);
3662 if ((void *)parameter != handler_data)
3663 fail("External entity ref handler parameter not correct");
3664
3665 /* Here we use the global 'parser' variable */
3666 ext_parser = XML_ExternalEntityParserCreate(g_parser, context, NULL);
3667 if (ext_parser == NULL)
3668 fail("Could not create external entity parser");
3669 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3670 == XML_STATUS_ERROR)
3671 xml_failure(ext_parser);
3672
3673 XML_ParserFree(ext_parser);
3674 return XML_STATUS_OK;
3675 }
3676
START_TEST(test_ext_entity_ref_parameter)3677 START_TEST(test_ext_entity_ref_parameter) {
3678 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
3679 "<!DOCTYPE doc SYSTEM 'foo'>\n"
3680 "<doc>&entity;</doc>";
3681
3682 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3683 XML_SetExternalEntityRefHandler(g_parser, external_entity_ref_param_checker);
3684 /* Set a handler arg that is not NULL and not parser (which is
3685 * what NULL would cause to be passed.
3686 */
3687 XML_SetExternalEntityRefHandlerArg(g_parser, (void *)text);
3688 handler_data = (void *)text;
3689 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3690 == XML_STATUS_ERROR)
3691 xml_failure(g_parser);
3692
3693 /* Now try again with unset args */
3694 XML_ParserReset(g_parser, NULL);
3695 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3696 XML_SetExternalEntityRefHandler(g_parser, external_entity_ref_param_checker);
3697 XML_SetExternalEntityRefHandlerArg(g_parser, NULL);
3698 handler_data = (void *)g_parser;
3699 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3700 == XML_STATUS_ERROR)
3701 xml_failure(g_parser);
3702 }
3703 END_TEST
3704
3705 /* Test the parsing of an empty string */
START_TEST(test_empty_parse)3706 START_TEST(test_empty_parse) {
3707 const char *text = "<doc></doc>";
3708 const char *partial = "<doc>";
3709
3710 if (XML_Parse(g_parser, NULL, 0, XML_FALSE) == XML_STATUS_ERROR)
3711 fail("Parsing empty string faulted");
3712 if (XML_Parse(g_parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR)
3713 fail("Parsing final empty string not faulted");
3714 if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_ELEMENTS)
3715 fail("Parsing final empty string faulted for wrong reason");
3716
3717 /* Now try with valid text before the empty end */
3718 XML_ParserReset(g_parser, NULL);
3719 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
3720 == XML_STATUS_ERROR)
3721 xml_failure(g_parser);
3722 if (XML_Parse(g_parser, NULL, 0, XML_TRUE) == XML_STATUS_ERROR)
3723 fail("Parsing final empty string faulted");
3724
3725 /* Now try with invalid text before the empty end */
3726 XML_ParserReset(g_parser, NULL);
3727 if (_XML_Parse_SINGLE_BYTES(g_parser, partial, (int)strlen(partial),
3728 XML_FALSE)
3729 == XML_STATUS_ERROR)
3730 xml_failure(g_parser);
3731 if (XML_Parse(g_parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR)
3732 fail("Parsing final incomplete empty string not faulted");
3733 }
3734 END_TEST
3735
3736 /* Test odd corners of the XML_GetBuffer interface */
3737 static enum XML_Status
get_feature(enum XML_FeatureEnum feature_id,long * presult)3738 get_feature(enum XML_FeatureEnum feature_id, long *presult) {
3739 const XML_Feature *feature = XML_GetFeatureList();
3740
3741 if (feature == NULL)
3742 return XML_STATUS_ERROR;
3743 for (; feature->feature != XML_FEATURE_END; feature++) {
3744 if (feature->feature == feature_id) {
3745 *presult = feature->value;
3746 return XML_STATUS_OK;
3747 }
3748 }
3749 return XML_STATUS_ERROR;
3750 }
3751
3752 /* Having an element name longer than 1024 characters exercises some
3753 * of the pool allocation code in the parser that otherwise does not
3754 * get executed. The count at the end of the line is the number of
3755 * characters (bytes) in the element name by that point.x
3756 */
3757 static const char *get_buffer_test_text
3758 = "<documentwitharidiculouslylongelementnametotease" /* 0x030 */
3759 "aparticularcorneroftheallocationinXML_GetBuffers" /* 0x060 */
3760 "othatwecanimprovethecoverageyetagain012345678901" /* 0x090 */
3761 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x0c0 */
3762 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x0f0 */
3763 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x120 */
3764 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x150 */
3765 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x180 */
3766 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x1b0 */
3767 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x1e0 */
3768 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x210 */
3769 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x240 */
3770 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x270 */
3771 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x2a0 */
3772 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x2d0 */
3773 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x300 */
3774 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x330 */
3775 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x360 */
3776 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x390 */
3777 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x3c0 */
3778 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x3f0 */
3779 "123456789abcdef0123456789abcdef0123456789>\n<ef0"; /* 0x420 */
3780
3781 /* Test odd corners of the XML_GetBuffer interface */
START_TEST(test_get_buffer_1)3782 START_TEST(test_get_buffer_1) {
3783 const char *text = get_buffer_test_text;
3784 void *buffer;
3785 long context_bytes;
3786
3787 /* Attempt to allocate a negative length buffer */
3788 if (XML_GetBuffer(g_parser, -12) != NULL)
3789 fail("Negative length buffer not failed");
3790
3791 /* Now get a small buffer and extend it past valid length */
3792 buffer = XML_GetBuffer(g_parser, 1536);
3793 if (buffer == NULL)
3794 fail("1.5K buffer failed");
3795 assert(buffer != NULL);
3796 memcpy(buffer, text, strlen(text));
3797 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE)
3798 == XML_STATUS_ERROR)
3799 xml_failure(g_parser);
3800 if (XML_GetBuffer(g_parser, INT_MAX) != NULL)
3801 fail("INT_MAX buffer not failed");
3802
3803 /* Now try extending it a more reasonable but still too large
3804 * amount. The allocator in XML_GetBuffer() doubles the buffer
3805 * size until it exceeds the requested amount or INT_MAX. If it
3806 * exceeds INT_MAX, it rejects the request, so we want a request
3807 * between INT_MAX and INT_MAX/2. A gap of 1K seems comfortable,
3808 * with an extra byte just to ensure that the request is off any
3809 * boundary. The request will be inflated internally by
3810 * XML_CONTEXT_BYTES (if defined), so we subtract that from our
3811 * request.
3812 */
3813 if (get_feature(XML_FEATURE_CONTEXT_BYTES, &context_bytes) != XML_STATUS_OK)
3814 context_bytes = 0;
3815 if (XML_GetBuffer(g_parser, INT_MAX - (context_bytes + 1025)) != NULL)
3816 fail("INT_MAX- buffer not failed");
3817
3818 /* Now try extending it a carefully crafted amount */
3819 if (XML_GetBuffer(g_parser, 1000) == NULL)
3820 fail("1000 buffer failed");
3821 }
3822 END_TEST
3823
3824 /* Test more corners of the XML_GetBuffer interface */
START_TEST(test_get_buffer_2)3825 START_TEST(test_get_buffer_2) {
3826 const char *text = get_buffer_test_text;
3827 void *buffer;
3828
3829 /* Now get a decent buffer */
3830 buffer = XML_GetBuffer(g_parser, 1536);
3831 if (buffer == NULL)
3832 fail("1.5K buffer failed");
3833 assert(buffer != NULL);
3834 memcpy(buffer, text, strlen(text));
3835 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE)
3836 == XML_STATUS_ERROR)
3837 xml_failure(g_parser);
3838
3839 /* Extend it, to catch a different code path */
3840 if (XML_GetBuffer(g_parser, 1024) == NULL)
3841 fail("1024 buffer failed");
3842 }
3843 END_TEST
3844
3845 /* Test position information macros */
START_TEST(test_byte_info_at_end)3846 START_TEST(test_byte_info_at_end) {
3847 const char *text = "<doc></doc>";
3848
3849 if (XML_GetCurrentByteIndex(g_parser) != -1
3850 || XML_GetCurrentByteCount(g_parser) != 0)
3851 fail("Byte index/count incorrect at start of parse");
3852 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3853 == XML_STATUS_ERROR)
3854 xml_failure(g_parser);
3855 /* At end, the count will be zero and the index the end of string */
3856 if (XML_GetCurrentByteCount(g_parser) != 0)
3857 fail("Terminal byte count incorrect");
3858 if (XML_GetCurrentByteIndex(g_parser) != (XML_Index)strlen(text))
3859 fail("Terminal byte index incorrect");
3860 }
3861 END_TEST
3862
3863 /* Test position information from errors */
3864 #define PRE_ERROR_STR "<doc></"
3865 #define POST_ERROR_STR "wombat></doc>"
START_TEST(test_byte_info_at_error)3866 START_TEST(test_byte_info_at_error) {
3867 const char *text = PRE_ERROR_STR POST_ERROR_STR;
3868
3869 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3870 == XML_STATUS_OK)
3871 fail("Syntax error not faulted");
3872 if (XML_GetCurrentByteCount(g_parser) != 0)
3873 fail("Error byte count incorrect");
3874 if (XML_GetCurrentByteIndex(g_parser) != strlen(PRE_ERROR_STR))
3875 fail("Error byte index incorrect");
3876 }
3877 END_TEST
3878 #undef PRE_ERROR_STR
3879 #undef POST_ERROR_STR
3880
3881 /* Test position information in handler */
3882 typedef struct ByteTestData {
3883 int start_element_len;
3884 int cdata_len;
3885 int total_string_len;
3886 } ByteTestData;
3887
3888 static void
byte_character_handler(void * userData,const XML_Char * s,int len)3889 byte_character_handler(void *userData, const XML_Char *s, int len) {
3890 #ifdef XML_CONTEXT_BYTES
3891 int offset, size;
3892 const char *buffer;
3893 ByteTestData *data = (ByteTestData *)userData;
3894
3895 UNUSED_P(s);
3896 buffer = XML_GetInputContext(g_parser, &offset, &size);
3897 if (buffer == NULL)
3898 fail("Failed to get context buffer");
3899 if (offset != data->start_element_len)
3900 fail("Context offset in unexpected position");
3901 if (len != data->cdata_len)
3902 fail("CDATA length reported incorrectly");
3903 if (size != data->total_string_len)
3904 fail("Context size is not full buffer");
3905 if (XML_GetCurrentByteIndex(g_parser) != offset)
3906 fail("Character byte index incorrect");
3907 if (XML_GetCurrentByteCount(g_parser) != len)
3908 fail("Character byte count incorrect");
3909 #else
3910 UNUSED_P(s);
3911 UNUSED_P(userData);
3912 UNUSED_P(len);
3913 #endif
3914 }
3915
3916 #define START_ELEMENT "<e>"
3917 #define CDATA_TEXT "Hello"
3918 #define END_ELEMENT "</e>"
START_TEST(test_byte_info_at_cdata)3919 START_TEST(test_byte_info_at_cdata) {
3920 const char *text = START_ELEMENT CDATA_TEXT END_ELEMENT;
3921 int offset, size;
3922 ByteTestData data;
3923
3924 /* Check initial context is empty */
3925 if (XML_GetInputContext(g_parser, &offset, &size) != NULL)
3926 fail("Unexpected context at start of parse");
3927
3928 data.start_element_len = (int)strlen(START_ELEMENT);
3929 data.cdata_len = (int)strlen(CDATA_TEXT);
3930 data.total_string_len = (int)strlen(text);
3931 XML_SetCharacterDataHandler(g_parser, byte_character_handler);
3932 XML_SetUserData(g_parser, &data);
3933 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_OK)
3934 xml_failure(g_parser);
3935 }
3936 END_TEST
3937 #undef START_ELEMENT
3938 #undef CDATA_TEXT
3939 #undef END_ELEMENT
3940
3941 /* Test predefined entities are correctly recognised */
START_TEST(test_predefined_entities)3942 START_TEST(test_predefined_entities) {
3943 const char *text = "<doc><>&"'</doc>";
3944 const XML_Char *expected = XCS("<doc><>&"'</doc>");
3945 const XML_Char *result = XCS("<>&\"'");
3946 CharData storage;
3947
3948 XML_SetDefaultHandler(g_parser, accumulate_characters);
3949 /* run_character_check uses XML_SetCharacterDataHandler(), which
3950 * unfortunately heads off a code path that we need to exercise.
3951 */
3952 CharData_Init(&storage);
3953 XML_SetUserData(g_parser, &storage);
3954 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3955 == XML_STATUS_ERROR)
3956 xml_failure(g_parser);
3957 /* The default handler doesn't translate the entities */
3958 CharData_CheckXMLChars(&storage, expected);
3959
3960 /* Now try again and check the translation */
3961 XML_ParserReset(g_parser, NULL);
3962 run_character_check(text, result);
3963 }
3964 END_TEST
3965
3966 /* Regression test that an invalid tag in an external parameter
3967 * reference in an external DTD is correctly faulted.
3968 *
3969 * Only a few specific tags are legal in DTDs ignoring comments and
3970 * processing instructions, all of which begin with an exclamation
3971 * mark. "<el/>" is not one of them, so the parser should raise an
3972 * error on encountering it.
3973 */
3974 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)3975 external_entity_param(XML_Parser parser, const XML_Char *context,
3976 const XML_Char *base, const XML_Char *systemId,
3977 const XML_Char *publicId) {
3978 const char *text1 = "<!ELEMENT doc EMPTY>\n"
3979 "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
3980 "<!ENTITY % e2 '%e1;'>\n"
3981 "%e1;\n";
3982 const char *text2 = "<!ELEMENT el EMPTY>\n"
3983 "<el/>\n";
3984 XML_Parser ext_parser;
3985
3986 UNUSED_P(base);
3987 UNUSED_P(publicId);
3988 if (systemId == NULL)
3989 return XML_STATUS_OK;
3990
3991 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3992 if (ext_parser == NULL)
3993 fail("Could not create external entity parser");
3994
3995 if (! xcstrcmp(systemId, XCS("004-1.ent"))) {
3996 if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
3997 != XML_STATUS_ERROR)
3998 fail("Inner DTD with invalid tag not rejected");
3999 if (XML_GetErrorCode(ext_parser) != XML_ERROR_EXTERNAL_ENTITY_HANDLING)
4000 xml_failure(ext_parser);
4001 } else if (! xcstrcmp(systemId, XCS("004-2.ent"))) {
4002 if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE)
4003 != XML_STATUS_ERROR)
4004 fail("Invalid tag in external param not rejected");
4005 if (XML_GetErrorCode(ext_parser) != XML_ERROR_SYNTAX)
4006 xml_failure(ext_parser);
4007 } else {
4008 fail("Unknown system ID");
4009 }
4010
4011 XML_ParserFree(ext_parser);
4012 return XML_STATUS_ERROR;
4013 }
4014
START_TEST(test_invalid_tag_in_dtd)4015 START_TEST(test_invalid_tag_in_dtd) {
4016 const char *text = "<!DOCTYPE doc SYSTEM '004-1.ent'>\n"
4017 "<doc></doc>\n";
4018
4019 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4020 XML_SetExternalEntityRefHandler(g_parser, external_entity_param);
4021 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
4022 "Invalid tag IN DTD external param not rejected");
4023 }
4024 END_TEST
4025
4026 /* Test entities not quite the predefined ones are not mis-recognised */
START_TEST(test_not_predefined_entities)4027 START_TEST(test_not_predefined_entities) {
4028 const char *text[] = {"<doc>&pt;</doc>", "<doc>&amo;</doc>",
4029 "<doc>&quid;</doc>", "<doc>&apod;</doc>", NULL};
4030 int i = 0;
4031
4032 while (text[i] != NULL) {
4033 expect_failure(text[i], XML_ERROR_UNDEFINED_ENTITY,
4034 "Undefined entity not rejected");
4035 XML_ParserReset(g_parser, NULL);
4036 i++;
4037 }
4038 }
4039 END_TEST
4040
4041 /* Test conditional inclusion (IGNORE) */
4042 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)4043 external_entity_load_ignore(XML_Parser parser, const XML_Char *context,
4044 const XML_Char *base, const XML_Char *systemId,
4045 const XML_Char *publicId) {
4046 const char *text = "<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>";
4047 XML_Parser ext_parser;
4048
4049 UNUSED_P(base);
4050 UNUSED_P(systemId);
4051 UNUSED_P(publicId);
4052 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4053 if (ext_parser == NULL)
4054 fail("Could not create external entity parser");
4055 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
4056 == XML_STATUS_ERROR)
4057 xml_failure(parser);
4058
4059 XML_ParserFree(ext_parser);
4060 return XML_STATUS_OK;
4061 }
4062
START_TEST(test_ignore_section)4063 START_TEST(test_ignore_section) {
4064 const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
4065 "<doc><e>&entity;</e></doc>";
4066 const XML_Char *expected
4067 = XCS("<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>\n&entity;");
4068 CharData storage;
4069
4070 CharData_Init(&storage);
4071 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4072 XML_SetUserData(g_parser, &storage);
4073 XML_SetExternalEntityRefHandler(g_parser, external_entity_load_ignore);
4074 XML_SetDefaultHandler(g_parser, accumulate_characters);
4075 XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler);
4076 XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler);
4077 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4078 XML_SetStartElementHandler(g_parser, dummy_start_element);
4079 XML_SetEndElementHandler(g_parser, dummy_end_element);
4080 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4081 == XML_STATUS_ERROR)
4082 xml_failure(g_parser);
4083 CharData_CheckXMLChars(&storage, expected);
4084 }
4085 END_TEST
4086
4087 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)4088 external_entity_load_ignore_utf16(XML_Parser parser, const XML_Char *context,
4089 const XML_Char *base,
4090 const XML_Char *systemId,
4091 const XML_Char *publicId) {
4092 const char text[] =
4093 /* <![IGNORE[<!ELEMENT e (#PCDATA)*>]]> */
4094 "<\0!\0[\0I\0G\0N\0O\0R\0E\0[\0"
4095 "<\0!\0E\0L\0E\0M\0E\0N\0T\0 \0e\0 \0"
4096 "(\0#\0P\0C\0D\0A\0T\0A\0)\0*\0>\0]\0]\0>\0";
4097 XML_Parser ext_parser;
4098
4099 UNUSED_P(base);
4100 UNUSED_P(systemId);
4101 UNUSED_P(publicId);
4102 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4103 if (ext_parser == NULL)
4104 fail("Could not create external entity parser");
4105 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)sizeof(text) - 1, XML_TRUE)
4106 == XML_STATUS_ERROR)
4107 xml_failure(parser);
4108
4109 XML_ParserFree(ext_parser);
4110 return XML_STATUS_OK;
4111 }
4112
START_TEST(test_ignore_section_utf16)4113 START_TEST(test_ignore_section_utf16) {
4114 const char text[] =
4115 /* <!DOCTYPE d SYSTEM 's'> */
4116 "<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 "
4117 "\0S\0Y\0S\0T\0E\0M\0 \0'\0s\0'\0>\0\n\0"
4118 /* <d><e>&en;</e></d> */
4119 "<\0d\0>\0<\0e\0>\0&\0e\0n\0;\0<\0/\0e\0>\0<\0/\0d\0>\0";
4120 const XML_Char *expected = XCS("<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>\n&en;");
4121 CharData storage;
4122
4123 CharData_Init(&storage);
4124 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4125 XML_SetUserData(g_parser, &storage);
4126 XML_SetExternalEntityRefHandler(g_parser, external_entity_load_ignore_utf16);
4127 XML_SetDefaultHandler(g_parser, accumulate_characters);
4128 XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler);
4129 XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler);
4130 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4131 XML_SetStartElementHandler(g_parser, dummy_start_element);
4132 XML_SetEndElementHandler(g_parser, dummy_end_element);
4133 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
4134 == XML_STATUS_ERROR)
4135 xml_failure(g_parser);
4136 CharData_CheckXMLChars(&storage, expected);
4137 }
4138 END_TEST
4139
4140 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)4141 external_entity_load_ignore_utf16_be(XML_Parser parser, const XML_Char *context,
4142 const XML_Char *base,
4143 const XML_Char *systemId,
4144 const XML_Char *publicId) {
4145 const char text[] =
4146 /* <![IGNORE[<!ELEMENT e (#PCDATA)*>]]> */
4147 "\0<\0!\0[\0I\0G\0N\0O\0R\0E\0["
4148 "\0<\0!\0E\0L\0E\0M\0E\0N\0T\0 \0e\0 "
4149 "\0(\0#\0P\0C\0D\0A\0T\0A\0)\0*\0>\0]\0]\0>";
4150 XML_Parser ext_parser;
4151
4152 UNUSED_P(base);
4153 UNUSED_P(systemId);
4154 UNUSED_P(publicId);
4155 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4156 if (ext_parser == NULL)
4157 fail("Could not create external entity parser");
4158 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)sizeof(text) - 1, XML_TRUE)
4159 == XML_STATUS_ERROR)
4160 xml_failure(parser);
4161
4162 XML_ParserFree(ext_parser);
4163 return XML_STATUS_OK;
4164 }
4165
START_TEST(test_ignore_section_utf16_be)4166 START_TEST(test_ignore_section_utf16_be) {
4167 const char text[] =
4168 /* <!DOCTYPE d SYSTEM 's'> */
4169 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 "
4170 "\0S\0Y\0S\0T\0E\0M\0 \0'\0s\0'\0>\0\n"
4171 /* <d><e>&en;</e></d> */
4172 "\0<\0d\0>\0<\0e\0>\0&\0e\0n\0;\0<\0/\0e\0>\0<\0/\0d\0>";
4173 const XML_Char *expected = XCS("<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>\n&en;");
4174 CharData storage;
4175
4176 CharData_Init(&storage);
4177 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4178 XML_SetUserData(g_parser, &storage);
4179 XML_SetExternalEntityRefHandler(g_parser,
4180 external_entity_load_ignore_utf16_be);
4181 XML_SetDefaultHandler(g_parser, accumulate_characters);
4182 XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler);
4183 XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler);
4184 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4185 XML_SetStartElementHandler(g_parser, dummy_start_element);
4186 XML_SetEndElementHandler(g_parser, dummy_end_element);
4187 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
4188 == XML_STATUS_ERROR)
4189 xml_failure(g_parser);
4190 CharData_CheckXMLChars(&storage, expected);
4191 }
4192 END_TEST
4193
4194 /* Test mis-formatted conditional exclusion */
START_TEST(test_bad_ignore_section)4195 START_TEST(test_bad_ignore_section) {
4196 const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
4197 "<doc><e>&entity;</e></doc>";
4198 ExtFaults faults[]
4199 = {{"<![IGNORE[<!ELEM", "Broken-off declaration not faulted", NULL,
4200 XML_ERROR_SYNTAX},
4201 {"<![IGNORE[\x01]]>", "Invalid XML character not faulted", NULL,
4202 XML_ERROR_INVALID_TOKEN},
4203 {/* FIrst two bytes of a three-byte char */
4204 "<![IGNORE[\xe2\x82", "Partial XML character not faulted", NULL,
4205 XML_ERROR_PARTIAL_CHAR},
4206 {NULL, NULL, NULL, XML_ERROR_NONE}};
4207 ExtFaults *fault;
4208
4209 for (fault = &faults[0]; fault->parse_text != NULL; fault++) {
4210 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4211 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
4212 XML_SetUserData(g_parser, fault);
4213 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
4214 "Incomplete IGNORE section not failed");
4215 XML_ParserReset(g_parser, NULL);
4216 }
4217 }
4218 END_TEST
4219
4220 /* Test recursive parsing */
4221 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)4222 external_entity_valuer(XML_Parser parser, const XML_Char *context,
4223 const XML_Char *base, const XML_Char *systemId,
4224 const XML_Char *publicId) {
4225 const char *text1 = "<!ELEMENT doc EMPTY>\n"
4226 "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
4227 "<!ENTITY % e2 '%e1;'>\n"
4228 "%e1;\n";
4229 XML_Parser ext_parser;
4230
4231 UNUSED_P(base);
4232 UNUSED_P(publicId);
4233 if (systemId == NULL)
4234 return XML_STATUS_OK;
4235 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4236 if (ext_parser == NULL)
4237 fail("Could not create external entity parser");
4238 if (! xcstrcmp(systemId, XCS("004-1.ent"))) {
4239 if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
4240 == XML_STATUS_ERROR)
4241 xml_failure(ext_parser);
4242 } else if (! xcstrcmp(systemId, XCS("004-2.ent"))) {
4243 ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser);
4244 enum XML_Status status;
4245 enum XML_Error error;
4246
4247 status = _XML_Parse_SINGLE_BYTES(ext_parser, fault->parse_text,
4248 (int)strlen(fault->parse_text), XML_TRUE);
4249 if (fault->error == XML_ERROR_NONE) {
4250 if (status == XML_STATUS_ERROR)
4251 xml_failure(ext_parser);
4252 } else {
4253 if (status != XML_STATUS_ERROR)
4254 fail(fault->fail_text);
4255 error = XML_GetErrorCode(ext_parser);
4256 if (error != fault->error
4257 && (fault->error != XML_ERROR_XML_DECL
4258 || error != XML_ERROR_TEXT_DECL))
4259 xml_failure(ext_parser);
4260 }
4261 }
4262
4263 XML_ParserFree(ext_parser);
4264 return XML_STATUS_OK;
4265 }
4266
START_TEST(test_external_entity_values)4267 START_TEST(test_external_entity_values) {
4268 const char *text = "<!DOCTYPE doc SYSTEM '004-1.ent'>\n"
4269 "<doc></doc>\n";
4270 ExtFaults data_004_2[] = {
4271 {"<!ATTLIST doc a1 CDATA 'value'>", NULL, NULL, XML_ERROR_NONE},
4272 {"<!ATTLIST $doc a1 CDATA 'value'>", "Invalid token not faulted", NULL,
4273 XML_ERROR_INVALID_TOKEN},
4274 {"'wombat", "Unterminated string not faulted", NULL,
4275 XML_ERROR_UNCLOSED_TOKEN},
4276 {"\xe2\x82", "Partial UTF-8 character not faulted", NULL,
4277 XML_ERROR_PARTIAL_CHAR},
4278 {"<?xml version='1.0' encoding='utf-8'?>\n", NULL, NULL, XML_ERROR_NONE},
4279 {"<?xml?>", "Malformed XML declaration not faulted", NULL,
4280 XML_ERROR_XML_DECL},
4281 {/* UTF-8 BOM */
4282 "\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>", NULL, NULL,
4283 XML_ERROR_NONE},
4284 {"<?xml version='1.0' encoding='utf-8'?>\n$",
4285 "Invalid token after text declaration not faulted", NULL,
4286 XML_ERROR_INVALID_TOKEN},
4287 {"<?xml version='1.0' encoding='utf-8'?>\n'wombat",
4288 "Unterminated string after text decl not faulted", NULL,
4289 XML_ERROR_UNCLOSED_TOKEN},
4290 {"<?xml version='1.0' encoding='utf-8'?>\n\xe2\x82",
4291 "Partial UTF-8 character after text decl not faulted", NULL,
4292 XML_ERROR_PARTIAL_CHAR},
4293 {"%e1;", "Recursive parameter entity not faulted", NULL,
4294 XML_ERROR_RECURSIVE_ENTITY_REF},
4295 {NULL, NULL, NULL, XML_ERROR_NONE}};
4296 int i;
4297
4298 for (i = 0; data_004_2[i].parse_text != NULL; i++) {
4299 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4300 XML_SetExternalEntityRefHandler(g_parser, external_entity_valuer);
4301 XML_SetUserData(g_parser, &data_004_2[i]);
4302 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4303 == XML_STATUS_ERROR)
4304 xml_failure(g_parser);
4305 XML_ParserReset(g_parser, NULL);
4306 }
4307 }
4308 END_TEST
4309
4310 /* Test the recursive parse interacts with a not standalone handler */
4311 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)4312 external_entity_not_standalone(XML_Parser parser, const XML_Char *context,
4313 const XML_Char *base, const XML_Char *systemId,
4314 const XML_Char *publicId) {
4315 const char *text1 = "<!ELEMENT doc EMPTY>\n"
4316 "<!ENTITY % e1 SYSTEM 'bar'>\n"
4317 "%e1;\n";
4318 const char *text2 = "<!ATTLIST doc a1 CDATA 'value'>";
4319 XML_Parser ext_parser;
4320
4321 UNUSED_P(base);
4322 UNUSED_P(publicId);
4323 if (systemId == NULL)
4324 return XML_STATUS_OK;
4325 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4326 if (ext_parser == NULL)
4327 fail("Could not create external entity parser");
4328 if (! xcstrcmp(systemId, XCS("foo"))) {
4329 XML_SetNotStandaloneHandler(ext_parser, reject_not_standalone_handler);
4330 if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
4331 != XML_STATUS_ERROR)
4332 fail("Expected not standalone rejection");
4333 if (XML_GetErrorCode(ext_parser) != XML_ERROR_NOT_STANDALONE)
4334 xml_failure(ext_parser);
4335 XML_SetNotStandaloneHandler(ext_parser, NULL);
4336 XML_ParserFree(ext_parser);
4337 return XML_STATUS_ERROR;
4338 } else if (! xcstrcmp(systemId, XCS("bar"))) {
4339 if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE)
4340 == XML_STATUS_ERROR)
4341 xml_failure(ext_parser);
4342 }
4343
4344 XML_ParserFree(ext_parser);
4345 return XML_STATUS_OK;
4346 }
4347
START_TEST(test_ext_entity_not_standalone)4348 START_TEST(test_ext_entity_not_standalone) {
4349 const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
4350 "<doc></doc>";
4351
4352 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4353 XML_SetExternalEntityRefHandler(g_parser, external_entity_not_standalone);
4354 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
4355 "Standalone rejection not caught");
4356 }
4357 END_TEST
4358
4359 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)4360 external_entity_value_aborter(XML_Parser parser, const XML_Char *context,
4361 const XML_Char *base, const XML_Char *systemId,
4362 const XML_Char *publicId) {
4363 const char *text1 = "<!ELEMENT doc EMPTY>\n"
4364 "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
4365 "<!ENTITY % e2 '%e1;'>\n"
4366 "%e1;\n";
4367 const char *text2 = "<?xml version='1.0' encoding='utf-8'?>";
4368 XML_Parser ext_parser;
4369
4370 UNUSED_P(base);
4371 UNUSED_P(publicId);
4372 if (systemId == NULL)
4373 return XML_STATUS_OK;
4374 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4375 if (ext_parser == NULL)
4376 fail("Could not create external entity parser");
4377 if (! xcstrcmp(systemId, XCS("004-1.ent"))) {
4378 if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
4379 == XML_STATUS_ERROR)
4380 xml_failure(ext_parser);
4381 }
4382 if (! xcstrcmp(systemId, XCS("004-2.ent"))) {
4383 XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
4384 XML_SetUserData(ext_parser, ext_parser);
4385 if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE)
4386 != XML_STATUS_ERROR)
4387 fail("Aborted parse not faulted");
4388 if (XML_GetErrorCode(ext_parser) != XML_ERROR_ABORTED)
4389 xml_failure(ext_parser);
4390 }
4391
4392 XML_ParserFree(ext_parser);
4393 return XML_STATUS_OK;
4394 }
4395
START_TEST(test_ext_entity_value_abort)4396 START_TEST(test_ext_entity_value_abort) {
4397 const char *text = "<!DOCTYPE doc SYSTEM '004-1.ent'>\n"
4398 "<doc></doc>\n";
4399
4400 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4401 XML_SetExternalEntityRefHandler(g_parser, external_entity_value_aborter);
4402 resumable = XML_FALSE;
4403 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4404 == XML_STATUS_ERROR)
4405 xml_failure(g_parser);
4406 }
4407 END_TEST
4408
START_TEST(test_bad_public_doctype)4409 START_TEST(test_bad_public_doctype) {
4410 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
4411 "<!DOCTYPE doc PUBLIC '{BadName}' 'test'>\n"
4412 "<doc></doc>";
4413
4414 /* Setting a handler provokes a particular code path */
4415 XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_handler,
4416 dummy_end_doctype_handler);
4417 expect_failure(text, XML_ERROR_PUBLICID, "Bad Public ID not failed");
4418 }
4419 END_TEST
4420
4421 /* Test based on ibm/valid/P32/ibm32v04.xml */
START_TEST(test_attribute_enum_value)4422 START_TEST(test_attribute_enum_value) {
4423 const char *text = "<?xml version='1.0' standalone='no'?>\n"
4424 "<!DOCTYPE animal SYSTEM 'test.dtd'>\n"
4425 "<animal>This is a \n <a/> \n\nyellow tiger</animal>";
4426 ExtTest dtd_data
4427 = {"<!ELEMENT animal (#PCDATA|a)*>\n"
4428 "<!ELEMENT a EMPTY>\n"
4429 "<!ATTLIST animal xml:space (default|preserve) 'preserve'>",
4430 NULL, NULL};
4431 const XML_Char *expected = XCS("This is a \n \n\nyellow tiger");
4432
4433 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
4434 XML_SetUserData(g_parser, &dtd_data);
4435 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4436 /* An attribute list handler provokes a different code path */
4437 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
4438 run_ext_character_check(text, &dtd_data, expected);
4439 }
4440 END_TEST
4441
4442 /* Slightly bizarrely, the library seems to silently ignore entity
4443 * definitions for predefined entities, even when they are wrong. The
4444 * language of the XML 1.0 spec is somewhat unhelpful as to what ought
4445 * to happen, so this is currently treated as acceptable.
4446 */
START_TEST(test_predefined_entity_redefinition)4447 START_TEST(test_predefined_entity_redefinition) {
4448 const char *text = "<!DOCTYPE doc [\n"
4449 "<!ENTITY apos 'foo'>\n"
4450 "]>\n"
4451 "<doc>'</doc>";
4452 run_character_check(text, XCS("'"));
4453 }
4454 END_TEST
4455
4456 /* Test that the parser stops processing the DTD after an unresolved
4457 * parameter entity is encountered.
4458 */
START_TEST(test_dtd_stop_processing)4459 START_TEST(test_dtd_stop_processing) {
4460 const char *text = "<!DOCTYPE doc [\n"
4461 "%foo;\n"
4462 "<!ENTITY bar 'bas'>\n"
4463 "]><doc/>";
4464
4465 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
4466 dummy_handler_flags = 0;
4467 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4468 == XML_STATUS_ERROR)
4469 xml_failure(g_parser);
4470 if (dummy_handler_flags != 0)
4471 fail("DTD processing still going after undefined PE");
4472 }
4473 END_TEST
4474
4475 /* Test public notations with no system ID */
START_TEST(test_public_notation_no_sysid)4476 START_TEST(test_public_notation_no_sysid) {
4477 const char *text = "<!DOCTYPE doc [\n"
4478 "<!NOTATION note PUBLIC 'foo'>\n"
4479 "<!ELEMENT doc EMPTY>\n"
4480 "]>\n<doc/>";
4481
4482 dummy_handler_flags = 0;
4483 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
4484 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4485 == XML_STATUS_ERROR)
4486 xml_failure(g_parser);
4487 if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG)
4488 fail("Notation declaration handler not called");
4489 }
4490 END_TEST
4491
4492 static void XMLCALL
record_element_start_handler(void * userData,const XML_Char * name,const XML_Char ** atts)4493 record_element_start_handler(void *userData, const XML_Char *name,
4494 const XML_Char **atts) {
4495 UNUSED_P(atts);
4496 CharData_AppendXMLChars((CharData *)userData, name, (int)xcstrlen(name));
4497 }
4498
START_TEST(test_nested_groups)4499 START_TEST(test_nested_groups) {
4500 const char *text
4501 = "<!DOCTYPE doc [\n"
4502 "<!ELEMENT doc "
4503 /* Sixteen elements per line */
4504 "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,"
4505 "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?"
4506 "))))))))))))))))))))))))))))))))>\n"
4507 "<!ELEMENT e EMPTY>"
4508 "]>\n"
4509 "<doc><e/></doc>";
4510 CharData storage;
4511
4512 CharData_Init(&storage);
4513 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4514 XML_SetStartElementHandler(g_parser, record_element_start_handler);
4515 XML_SetUserData(g_parser, &storage);
4516 dummy_handler_flags = 0;
4517 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4518 == XML_STATUS_ERROR)
4519 xml_failure(g_parser);
4520 CharData_CheckXMLChars(&storage, XCS("doce"));
4521 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
4522 fail("Element handler not fired");
4523 }
4524 END_TEST
4525
START_TEST(test_group_choice)4526 START_TEST(test_group_choice) {
4527 const char *text = "<!DOCTYPE doc [\n"
4528 "<!ELEMENT doc (a|b|c)+>\n"
4529 "<!ELEMENT a EMPTY>\n"
4530 "<!ELEMENT b (#PCDATA)>\n"
4531 "<!ELEMENT c ANY>\n"
4532 "]>\n"
4533 "<doc>\n"
4534 "<a/>\n"
4535 "<b attr='foo'>This is a foo</b>\n"
4536 "<c></c>\n"
4537 "</doc>\n";
4538
4539 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4540 dummy_handler_flags = 0;
4541 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4542 == XML_STATUS_ERROR)
4543 xml_failure(g_parser);
4544 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
4545 fail("Element handler flag not raised");
4546 }
4547 END_TEST
4548
4549 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)4550 external_entity_public(XML_Parser parser, const XML_Char *context,
4551 const XML_Char *base, const XML_Char *systemId,
4552 const XML_Char *publicId) {
4553 const char *text1 = (const char *)XML_GetUserData(parser);
4554 const char *text2 = "<!ATTLIST doc a CDATA 'value'>";
4555 const char *text = NULL;
4556 XML_Parser ext_parser;
4557 int parse_res;
4558
4559 UNUSED_P(base);
4560 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4561 if (ext_parser == NULL)
4562 return XML_STATUS_ERROR;
4563 if (systemId != NULL && ! xcstrcmp(systemId, XCS("http://example.org/"))) {
4564 text = text1;
4565 } else if (publicId != NULL && ! xcstrcmp(publicId, XCS("foo"))) {
4566 text = text2;
4567 } else
4568 fail("Unexpected parameters to external entity parser");
4569 assert(text != NULL);
4570 parse_res
4571 = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
4572 XML_ParserFree(ext_parser);
4573 return parse_res;
4574 }
4575
START_TEST(test_standalone_parameter_entity)4576 START_TEST(test_standalone_parameter_entity) {
4577 const char *text = "<?xml version='1.0' standalone='yes'?>\n"
4578 "<!DOCTYPE doc SYSTEM 'http://example.org/' [\n"
4579 "<!ENTITY % entity '<!ELEMENT doc (#PCDATA)>'>\n"
4580 "%entity;\n"
4581 "]>\n"
4582 "<doc></doc>";
4583 char dtd_data[] = "<!ENTITY % e1 'foo'>\n";
4584
4585 XML_SetUserData(g_parser, dtd_data);
4586 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4587 XML_SetExternalEntityRefHandler(g_parser, external_entity_public);
4588 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4589 == XML_STATUS_ERROR)
4590 xml_failure(g_parser);
4591 }
4592 END_TEST
4593
4594 /* Test skipping of parameter entity in an external DTD */
4595 /* Derived from ibm/invalid/P69/ibm69i01.xml */
START_TEST(test_skipped_parameter_entity)4596 START_TEST(test_skipped_parameter_entity) {
4597 const char *text = "<?xml version='1.0'?>\n"
4598 "<!DOCTYPE root SYSTEM 'http://example.org/dtd.ent' [\n"
4599 "<!ELEMENT root (#PCDATA|a)* >\n"
4600 "]>\n"
4601 "<root></root>";
4602 ExtTest dtd_data = {"%pe2;", NULL, NULL};
4603
4604 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
4605 XML_SetUserData(g_parser, &dtd_data);
4606 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4607 XML_SetSkippedEntityHandler(g_parser, dummy_skip_handler);
4608 dummy_handler_flags = 0;
4609 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4610 == XML_STATUS_ERROR)
4611 xml_failure(g_parser);
4612 if (dummy_handler_flags != DUMMY_SKIP_HANDLER_FLAG)
4613 fail("Skip handler not executed");
4614 }
4615 END_TEST
4616
4617 /* Test recursive parameter entity definition rejected in external DTD */
START_TEST(test_recursive_external_parameter_entity)4618 START_TEST(test_recursive_external_parameter_entity) {
4619 const char *text = "<?xml version='1.0'?>\n"
4620 "<!DOCTYPE root SYSTEM 'http://example.org/dtd.ent' [\n"
4621 "<!ELEMENT root (#PCDATA|a)* >\n"
4622 "]>\n"
4623 "<root></root>";
4624 ExtFaults dtd_data = {"<!ENTITY % pe2 '%pe2;'>\n%pe2;",
4625 "Recursive external parameter entity not faulted", NULL,
4626 XML_ERROR_RECURSIVE_ENTITY_REF};
4627
4628 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
4629 XML_SetUserData(g_parser, &dtd_data);
4630 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4631 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
4632 "Recursive external parameter not spotted");
4633 }
4634 END_TEST
4635
4636 /* Test undefined parameter entity in external entity handler */
4637 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)4638 external_entity_devaluer(XML_Parser parser, const XML_Char *context,
4639 const XML_Char *base, const XML_Char *systemId,
4640 const XML_Char *publicId) {
4641 const char *text = "<!ELEMENT doc EMPTY>\n"
4642 "<!ENTITY % e1 SYSTEM 'bar'>\n"
4643 "%e1;\n";
4644 XML_Parser ext_parser;
4645 intptr_t clear_handler = (intptr_t)XML_GetUserData(parser);
4646
4647 UNUSED_P(base);
4648 UNUSED_P(publicId);
4649 if (systemId == NULL || ! xcstrcmp(systemId, XCS("bar")))
4650 return XML_STATUS_OK;
4651 if (xcstrcmp(systemId, XCS("foo")))
4652 fail("Unexpected system ID");
4653 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4654 if (ext_parser == NULL)
4655 fail("Could note create external entity parser");
4656 if (clear_handler)
4657 XML_SetExternalEntityRefHandler(ext_parser, NULL);
4658 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
4659 == XML_STATUS_ERROR)
4660 xml_failure(ext_parser);
4661
4662 XML_ParserFree(ext_parser);
4663 return XML_STATUS_OK;
4664 }
4665
START_TEST(test_undefined_ext_entity_in_external_dtd)4666 START_TEST(test_undefined_ext_entity_in_external_dtd) {
4667 const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
4668 "<doc></doc>\n";
4669
4670 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4671 XML_SetExternalEntityRefHandler(g_parser, external_entity_devaluer);
4672 XML_SetUserData(g_parser, (void *)(intptr_t)XML_FALSE);
4673 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4674 == XML_STATUS_ERROR)
4675 xml_failure(g_parser);
4676
4677 /* Now repeat without the external entity ref handler invoking
4678 * another copy of itself.
4679 */
4680 XML_ParserReset(g_parser, NULL);
4681 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4682 XML_SetExternalEntityRefHandler(g_parser, external_entity_devaluer);
4683 XML_SetUserData(g_parser, (void *)(intptr_t)XML_TRUE);
4684 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4685 == XML_STATUS_ERROR)
4686 xml_failure(g_parser);
4687 }
4688 END_TEST
4689
4690 static void XMLCALL
aborting_xdecl_handler(void * userData,const XML_Char * version,const XML_Char * encoding,int standalone)4691 aborting_xdecl_handler(void *userData, const XML_Char *version,
4692 const XML_Char *encoding, int standalone) {
4693 UNUSED_P(userData);
4694 UNUSED_P(version);
4695 UNUSED_P(encoding);
4696 UNUSED_P(standalone);
4697 XML_StopParser(g_parser, resumable);
4698 XML_SetXmlDeclHandler(g_parser, NULL);
4699 }
4700
4701 /* Test suspending the parse on receiving an XML declaration works */
START_TEST(test_suspend_xdecl)4702 START_TEST(test_suspend_xdecl) {
4703 const char *text = long_character_data_text;
4704
4705 XML_SetXmlDeclHandler(g_parser, aborting_xdecl_handler);
4706 resumable = XML_TRUE;
4707 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4708 != XML_STATUS_SUSPENDED)
4709 xml_failure(g_parser);
4710 if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE)
4711 xml_failure(g_parser);
4712 /* Attempt to start a new parse while suspended */
4713 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
4714 != XML_STATUS_ERROR)
4715 fail("Attempt to parse while suspended not faulted");
4716 if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED)
4717 fail("Suspended parse not faulted with correct error");
4718 }
4719 END_TEST
4720
4721 /* Test aborting the parse in an epilog works */
4722 static void XMLCALL
selective_aborting_default_handler(void * userData,const XML_Char * s,int len)4723 selective_aborting_default_handler(void *userData, const XML_Char *s, int len) {
4724 const XML_Char *match = (const XML_Char *)userData;
4725
4726 if (match == NULL
4727 || (xcstrlen(match) == (unsigned)len && ! xcstrncmp(match, s, len))) {
4728 XML_StopParser(g_parser, resumable);
4729 XML_SetDefaultHandler(g_parser, NULL);
4730 }
4731 }
4732
START_TEST(test_abort_epilog)4733 START_TEST(test_abort_epilog) {
4734 const char *text = "<doc></doc>\n\r\n";
4735 XML_Char match[] = XCS("\r");
4736
4737 XML_SetDefaultHandler(g_parser, selective_aborting_default_handler);
4738 XML_SetUserData(g_parser, match);
4739 resumable = XML_FALSE;
4740 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4741 != XML_STATUS_ERROR)
4742 fail("Abort not triggered");
4743 if (XML_GetErrorCode(g_parser) != XML_ERROR_ABORTED)
4744 xml_failure(g_parser);
4745 }
4746 END_TEST
4747
4748 /* Test a different code path for abort in the epilog */
START_TEST(test_abort_epilog_2)4749 START_TEST(test_abort_epilog_2) {
4750 const char *text = "<doc></doc>\n";
4751 XML_Char match[] = XCS("\n");
4752
4753 XML_SetDefaultHandler(g_parser, selective_aborting_default_handler);
4754 XML_SetUserData(g_parser, match);
4755 resumable = XML_FALSE;
4756 expect_failure(text, XML_ERROR_ABORTED, "Abort not triggered");
4757 }
4758 END_TEST
4759
4760 /* Test suspension from the epilog */
START_TEST(test_suspend_epilog)4761 START_TEST(test_suspend_epilog) {
4762 const char *text = "<doc></doc>\n";
4763 XML_Char match[] = XCS("\n");
4764
4765 XML_SetDefaultHandler(g_parser, selective_aborting_default_handler);
4766 XML_SetUserData(g_parser, match);
4767 resumable = XML_TRUE;
4768 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4769 != XML_STATUS_SUSPENDED)
4770 xml_failure(g_parser);
4771 }
4772 END_TEST
4773
4774 static void XMLCALL
suspending_end_handler(void * userData,const XML_Char * s)4775 suspending_end_handler(void *userData, const XML_Char *s) {
4776 UNUSED_P(s);
4777 XML_StopParser((XML_Parser)userData, 1);
4778 }
4779
START_TEST(test_suspend_in_sole_empty_tag)4780 START_TEST(test_suspend_in_sole_empty_tag) {
4781 const char *text = "<doc/>";
4782 enum XML_Status rc;
4783
4784 XML_SetEndElementHandler(g_parser, suspending_end_handler);
4785 XML_SetUserData(g_parser, g_parser);
4786 rc = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE);
4787 if (rc == XML_STATUS_ERROR)
4788 xml_failure(g_parser);
4789 else if (rc != XML_STATUS_SUSPENDED)
4790 fail("Suspend not triggered");
4791 rc = XML_ResumeParser(g_parser);
4792 if (rc == XML_STATUS_ERROR)
4793 xml_failure(g_parser);
4794 else if (rc != XML_STATUS_OK)
4795 fail("Resume failed");
4796 }
4797 END_TEST
4798
START_TEST(test_unfinished_epilog)4799 START_TEST(test_unfinished_epilog) {
4800 const char *text = "<doc></doc><";
4801
4802 expect_failure(text, XML_ERROR_UNCLOSED_TOKEN,
4803 "Incomplete epilog entry not faulted");
4804 }
4805 END_TEST
4806
START_TEST(test_partial_char_in_epilog)4807 START_TEST(test_partial_char_in_epilog) {
4808 const char *text = "<doc></doc>\xe2\x82";
4809
4810 /* First check that no fault is raised if the parse is not finished */
4811 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
4812 == XML_STATUS_ERROR)
4813 xml_failure(g_parser);
4814 /* Now check that it is faulted once we finish */
4815 if (XML_ParseBuffer(g_parser, 0, XML_TRUE) != XML_STATUS_ERROR)
4816 fail("Partial character in epilog not faulted");
4817 if (XML_GetErrorCode(g_parser) != XML_ERROR_PARTIAL_CHAR)
4818 xml_failure(g_parser);
4819 }
4820 END_TEST
4821
START_TEST(test_hash_collision)4822 START_TEST(test_hash_collision) {
4823 /* For full coverage of the lookup routine, we need to ensure a
4824 * hash collision even though we can only tell that we have one
4825 * through breakpoint debugging or coverage statistics. The
4826 * following will cause a hash collision on machines with a 64-bit
4827 * long type; others will have to experiment. The full coverage
4828 * tests invoked from qa.sh usually provide a hash collision, but
4829 * not always. This is an attempt to provide insurance.
4830 */
4831 #define COLLIDING_HASH_SALT (unsigned long)_SIP_ULL(0xffffffffU, 0xff99fc90U)
4832 const char *text
4833 = "<doc>\n"
4834 "<a1/><a2/><a3/><a4/><a5/><a6/><a7/><a8/>\n"
4835 "<b1></b1><b2 attr='foo'>This is a foo</b2><b3></b3><b4></b4>\n"
4836 "<b5></b5><b6></b6><b7></b7><b8></b8>\n"
4837 "<c1/><c2/><c3/><c4/><c5/><c6/><c7/><c8/>\n"
4838 "<d1/><d2/><d3/><d4/><d5/><d6/><d7/>\n"
4839 "<d8>This triggers the table growth and collides with b2</d8>\n"
4840 "</doc>\n";
4841
4842 XML_SetHashSalt(g_parser, COLLIDING_HASH_SALT);
4843 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4844 == XML_STATUS_ERROR)
4845 xml_failure(g_parser);
4846 }
4847 END_TEST
4848 #undef COLLIDING_HASH_SALT
4849
4850 /* Test resuming a parse suspended in entity substitution */
4851 static void XMLCALL
start_element_suspender(void * userData,const XML_Char * name,const XML_Char ** atts)4852 start_element_suspender(void *userData, const XML_Char *name,
4853 const XML_Char **atts) {
4854 UNUSED_P(userData);
4855 UNUSED_P(atts);
4856 if (! xcstrcmp(name, XCS("suspend")))
4857 XML_StopParser(g_parser, XML_TRUE);
4858 if (! xcstrcmp(name, XCS("abort")))
4859 XML_StopParser(g_parser, XML_FALSE);
4860 }
4861
START_TEST(test_suspend_resume_internal_entity)4862 START_TEST(test_suspend_resume_internal_entity) {
4863 const char *text
4864 = "<!DOCTYPE doc [\n"
4865 "<!ENTITY foo '<suspend>Hi<suspend>Ho</suspend></suspend>'>\n"
4866 "]>\n"
4867 "<doc>&foo;</doc>\n";
4868 const XML_Char *expected1 = XCS("Hi");
4869 const XML_Char *expected2 = XCS("HiHo");
4870 CharData storage;
4871
4872 CharData_Init(&storage);
4873 XML_SetStartElementHandler(g_parser, start_element_suspender);
4874 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
4875 XML_SetUserData(g_parser, &storage);
4876 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
4877 != XML_STATUS_SUSPENDED)
4878 xml_failure(g_parser);
4879 CharData_CheckXMLChars(&storage, XCS(""));
4880 if (XML_ResumeParser(g_parser) != XML_STATUS_SUSPENDED)
4881 xml_failure(g_parser);
4882 CharData_CheckXMLChars(&storage, expected1);
4883 if (XML_ResumeParser(g_parser) != XML_STATUS_OK)
4884 xml_failure(g_parser);
4885 CharData_CheckXMLChars(&storage, expected2);
4886 }
4887 END_TEST
4888
4889 /* Test syntax error is caught at parse resumption */
START_TEST(test_resume_entity_with_syntax_error)4890 START_TEST(test_resume_entity_with_syntax_error) {
4891 const char *text = "<!DOCTYPE doc [\n"
4892 "<!ENTITY foo '<suspend>Hi</wombat>'>\n"
4893 "]>\n"
4894 "<doc>&foo;</doc>\n";
4895
4896 XML_SetStartElementHandler(g_parser, start_element_suspender);
4897 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
4898 != XML_STATUS_SUSPENDED)
4899 xml_failure(g_parser);
4900 if (XML_ResumeParser(g_parser) != XML_STATUS_ERROR)
4901 fail("Syntax error in entity not faulted");
4902 if (XML_GetErrorCode(g_parser) != XML_ERROR_TAG_MISMATCH)
4903 xml_failure(g_parser);
4904 }
4905 END_TEST
4906
4907 /* Test suspending and resuming in a parameter entity substitution */
4908 static void XMLCALL
element_decl_suspender(void * userData,const XML_Char * name,XML_Content * model)4909 element_decl_suspender(void *userData, const XML_Char *name,
4910 XML_Content *model) {
4911 UNUSED_P(userData);
4912 UNUSED_P(name);
4913 XML_StopParser(g_parser, XML_TRUE);
4914 XML_FreeContentModel(g_parser, model);
4915 }
4916
START_TEST(test_suspend_resume_parameter_entity)4917 START_TEST(test_suspend_resume_parameter_entity) {
4918 const char *text = "<!DOCTYPE doc [\n"
4919 "<!ENTITY % foo '<!ELEMENT doc (#PCDATA)*>'>\n"
4920 "%foo;\n"
4921 "]>\n"
4922 "<doc>Hello, world</doc>";
4923 const XML_Char *expected = XCS("Hello, world");
4924 CharData storage;
4925
4926 CharData_Init(&storage);
4927 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4928 XML_SetElementDeclHandler(g_parser, element_decl_suspender);
4929 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
4930 XML_SetUserData(g_parser, &storage);
4931 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
4932 != XML_STATUS_SUSPENDED)
4933 xml_failure(g_parser);
4934 CharData_CheckXMLChars(&storage, XCS(""));
4935 if (XML_ResumeParser(g_parser) != XML_STATUS_OK)
4936 xml_failure(g_parser);
4937 CharData_CheckXMLChars(&storage, expected);
4938 }
4939 END_TEST
4940
4941 /* Test attempting to use parser after an error is faulted */
START_TEST(test_restart_on_error)4942 START_TEST(test_restart_on_error) {
4943 const char *text = "<$doc><doc></doc>";
4944
4945 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
4946 != XML_STATUS_ERROR)
4947 fail("Invalid tag name not faulted");
4948 if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
4949 xml_failure(g_parser);
4950 if (XML_Parse(g_parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR)
4951 fail("Restarting invalid parse not faulted");
4952 if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
4953 xml_failure(g_parser);
4954 }
4955 END_TEST
4956
4957 /* Test that angle brackets in an attribute default value are faulted */
START_TEST(test_reject_lt_in_attribute_value)4958 START_TEST(test_reject_lt_in_attribute_value) {
4959 const char *text = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '<bar>'>]>\n"
4960 "<doc></doc>";
4961
4962 expect_failure(text, XML_ERROR_INVALID_TOKEN,
4963 "Bad attribute default not faulted");
4964 }
4965 END_TEST
4966
START_TEST(test_reject_unfinished_param_in_att_value)4967 START_TEST(test_reject_unfinished_param_in_att_value) {
4968 const char *text = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '&foo'>]>\n"
4969 "<doc></doc>";
4970
4971 expect_failure(text, XML_ERROR_INVALID_TOKEN,
4972 "Bad attribute default not faulted");
4973 }
4974 END_TEST
4975
START_TEST(test_trailing_cr_in_att_value)4976 START_TEST(test_trailing_cr_in_att_value) {
4977 const char *text = "<doc a='value\r'/>";
4978
4979 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4980 == XML_STATUS_ERROR)
4981 xml_failure(g_parser);
4982 }
4983 END_TEST
4984
4985 /* Try parsing a general entity within a parameter entity in a
4986 * standalone internal DTD. Covers a corner case in the parser.
4987 */
START_TEST(test_standalone_internal_entity)4988 START_TEST(test_standalone_internal_entity) {
4989 const char *text = "<?xml version='1.0' standalone='yes' ?>\n"
4990 "<!DOCTYPE doc [\n"
4991 " <!ELEMENT doc (#PCDATA)>\n"
4992 " <!ENTITY % pe '<!ATTLIST doc att2 CDATA \"≥\">'>\n"
4993 " <!ENTITY ge 'AttDefaultValue'>\n"
4994 " %pe;\n"
4995 "]>\n"
4996 "<doc att2='any'/>";
4997
4998 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4999 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5000 == XML_STATUS_ERROR)
5001 xml_failure(g_parser);
5002 }
5003 END_TEST
5004
5005 /* Test that a reference to an unknown external entity is skipped */
START_TEST(test_skipped_external_entity)5006 START_TEST(test_skipped_external_entity) {
5007 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
5008 "<doc></doc>\n";
5009 ExtTest test_data = {"<!ELEMENT doc EMPTY>\n"
5010 "<!ENTITY % e2 '%e1;'>\n",
5011 NULL, NULL};
5012
5013 XML_SetUserData(g_parser, &test_data);
5014 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5015 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
5016 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5017 == XML_STATUS_ERROR)
5018 xml_failure(g_parser);
5019 }
5020 END_TEST
5021
5022 /* Test a different form of unknown external entity */
5023 typedef struct ext_hdlr_data {
5024 const char *parse_text;
5025 XML_ExternalEntityRefHandler handler;
5026 } ExtHdlrData;
5027
5028 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)5029 external_entity_oneshot_loader(XML_Parser parser, const XML_Char *context,
5030 const XML_Char *base, const XML_Char *systemId,
5031 const XML_Char *publicId) {
5032 ExtHdlrData *test_data = (ExtHdlrData *)XML_GetUserData(parser);
5033 XML_Parser ext_parser;
5034
5035 UNUSED_P(base);
5036 UNUSED_P(systemId);
5037 UNUSED_P(publicId);
5038 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
5039 if (ext_parser == NULL)
5040 fail("Could not create external entity parser.");
5041 /* Use the requested entity parser for further externals */
5042 XML_SetExternalEntityRefHandler(ext_parser, test_data->handler);
5043 if (_XML_Parse_SINGLE_BYTES(ext_parser, test_data->parse_text,
5044 (int)strlen(test_data->parse_text), XML_TRUE)
5045 == XML_STATUS_ERROR) {
5046 xml_failure(ext_parser);
5047 }
5048
5049 XML_ParserFree(ext_parser);
5050 return XML_STATUS_OK;
5051 }
5052
START_TEST(test_skipped_null_loaded_ext_entity)5053 START_TEST(test_skipped_null_loaded_ext_entity) {
5054 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n"
5055 "<doc />";
5056 ExtHdlrData test_data
5057 = {"<!ENTITY % pe1 SYSTEM 'http://example.org/two.ent'>\n"
5058 "<!ENTITY % pe2 '%pe1;'>\n"
5059 "%pe2;\n",
5060 external_entity_null_loader};
5061
5062 XML_SetUserData(g_parser, &test_data);
5063 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5064 XML_SetExternalEntityRefHandler(g_parser, external_entity_oneshot_loader);
5065 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5066 == XML_STATUS_ERROR)
5067 xml_failure(g_parser);
5068 }
5069 END_TEST
5070
START_TEST(test_skipped_unloaded_ext_entity)5071 START_TEST(test_skipped_unloaded_ext_entity) {
5072 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n"
5073 "<doc />";
5074 ExtHdlrData test_data
5075 = {"<!ENTITY % pe1 SYSTEM 'http://example.org/two.ent'>\n"
5076 "<!ENTITY % pe2 '%pe1;'>\n"
5077 "%pe2;\n",
5078 NULL};
5079
5080 XML_SetUserData(g_parser, &test_data);
5081 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5082 XML_SetExternalEntityRefHandler(g_parser, external_entity_oneshot_loader);
5083 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5084 == XML_STATUS_ERROR)
5085 xml_failure(g_parser);
5086 }
5087 END_TEST
5088
5089 /* Test that a parameter entity value ending with a carriage return
5090 * has it translated internally into a newline.
5091 */
START_TEST(test_param_entity_with_trailing_cr)5092 START_TEST(test_param_entity_with_trailing_cr) {
5093 #define PARAM_ENTITY_NAME "pe"
5094 #define PARAM_ENTITY_CORE_VALUE "<!ATTLIST doc att CDATA \"default\">"
5095 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
5096 "<doc/>";
5097 ExtTest test_data
5098 = {"<!ENTITY % " PARAM_ENTITY_NAME " '" PARAM_ENTITY_CORE_VALUE "\r'>\n"
5099 "%" PARAM_ENTITY_NAME ";\n",
5100 NULL, NULL};
5101
5102 XML_SetUserData(g_parser, &test_data);
5103 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5104 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
5105 XML_SetEntityDeclHandler(g_parser, param_entity_match_handler);
5106 entity_name_to_match = XCS(PARAM_ENTITY_NAME);
5107 entity_value_to_match = XCS(PARAM_ENTITY_CORE_VALUE) XCS("\n");
5108 entity_match_flag = ENTITY_MATCH_NOT_FOUND;
5109 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5110 == XML_STATUS_ERROR)
5111 xml_failure(g_parser);
5112 if (entity_match_flag == ENTITY_MATCH_FAIL)
5113 fail("Parameter entity CR->NEWLINE conversion failed");
5114 else if (entity_match_flag == ENTITY_MATCH_NOT_FOUND)
5115 fail("Parameter entity not parsed");
5116 }
5117 #undef PARAM_ENTITY_NAME
5118 #undef PARAM_ENTITY_CORE_VALUE
5119 END_TEST
5120
START_TEST(test_invalid_character_entity)5121 START_TEST(test_invalid_character_entity) {
5122 const char *text = "<!DOCTYPE doc [\n"
5123 " <!ENTITY entity '�'>\n"
5124 "]>\n"
5125 "<doc>&entity;</doc>";
5126
5127 expect_failure(text, XML_ERROR_BAD_CHAR_REF,
5128 "Out of range character reference not faulted");
5129 }
5130 END_TEST
5131
START_TEST(test_invalid_character_entity_2)5132 START_TEST(test_invalid_character_entity_2) {
5133 const char *text = "<!DOCTYPE doc [\n"
5134 " <!ENTITY entity '&#xg0;'>\n"
5135 "]>\n"
5136 "<doc>&entity;</doc>";
5137
5138 expect_failure(text, XML_ERROR_INVALID_TOKEN,
5139 "Out of range character reference not faulted");
5140 }
5141 END_TEST
5142
START_TEST(test_invalid_character_entity_3)5143 START_TEST(test_invalid_character_entity_3) {
5144 const char text[] =
5145 /* <!DOCTYPE doc [\n */
5146 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0\n"
5147 /* U+0E04 = KHO KHWAI
5148 * U+0E08 = CHO CHAN */
5149 /* <!ENTITY entity '&\u0e04\u0e08;'>\n */
5150 "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0e\0n\0t\0i\0t\0y\0 "
5151 "\0'\0&\x0e\x04\x0e\x08\0;\0'\0>\0\n"
5152 /* ]>\n */
5153 "\0]\0>\0\n"
5154 /* <doc>&entity;</doc> */
5155 "\0<\0d\0o\0c\0>\0&\0e\0n\0t\0i\0t\0y\0;\0<\0/\0d\0o\0c\0>";
5156
5157 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5158 != XML_STATUS_ERROR)
5159 fail("Invalid start of entity name not faulted");
5160 if (XML_GetErrorCode(g_parser) != XML_ERROR_UNDEFINED_ENTITY)
5161 xml_failure(g_parser);
5162 }
5163 END_TEST
5164
START_TEST(test_invalid_character_entity_4)5165 START_TEST(test_invalid_character_entity_4) {
5166 const char *text = "<!DOCTYPE doc [\n"
5167 " <!ENTITY entity '�'>\n" /* = � */
5168 "]>\n"
5169 "<doc>&entity;</doc>";
5170
5171 expect_failure(text, XML_ERROR_BAD_CHAR_REF,
5172 "Out of range character reference not faulted");
5173 }
5174 END_TEST
5175
5176 /* Test that processing instructions are picked up by a default handler */
START_TEST(test_pi_handled_in_default)5177 START_TEST(test_pi_handled_in_default) {
5178 const char *text = "<?test processing instruction?>\n<doc/>";
5179 const XML_Char *expected = XCS("<?test processing instruction?>\n<doc/>");
5180 CharData storage;
5181
5182 CharData_Init(&storage);
5183 XML_SetDefaultHandler(g_parser, accumulate_characters);
5184 XML_SetUserData(g_parser, &storage);
5185 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5186 == XML_STATUS_ERROR)
5187 xml_failure(g_parser);
5188 CharData_CheckXMLChars(&storage, expected);
5189 }
5190 END_TEST
5191
5192 /* Test that comments are picked up by a default handler */
START_TEST(test_comment_handled_in_default)5193 START_TEST(test_comment_handled_in_default) {
5194 const char *text = "<!-- This is a comment -->\n<doc/>";
5195 const XML_Char *expected = XCS("<!-- This is a comment -->\n<doc/>");
5196 CharData storage;
5197
5198 CharData_Init(&storage);
5199 XML_SetDefaultHandler(g_parser, accumulate_characters);
5200 XML_SetUserData(g_parser, &storage);
5201 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5202 == XML_STATUS_ERROR)
5203 xml_failure(g_parser);
5204 CharData_CheckXMLChars(&storage, expected);
5205 }
5206 END_TEST
5207
5208 /* Test PIs that look almost but not quite like XML declarations */
5209 static void XMLCALL
accumulate_pi_characters(void * userData,const XML_Char * target,const XML_Char * data)5210 accumulate_pi_characters(void *userData, const XML_Char *target,
5211 const XML_Char *data) {
5212 CharData *storage = (CharData *)userData;
5213
5214 CharData_AppendXMLChars(storage, target, -1);
5215 CharData_AppendXMLChars(storage, XCS(": "), 2);
5216 CharData_AppendXMLChars(storage, data, -1);
5217 CharData_AppendXMLChars(storage, XCS("\n"), 1);
5218 }
5219
START_TEST(test_pi_yml)5220 START_TEST(test_pi_yml) {
5221 const char *text = "<?yml something like data?><doc/>";
5222 const XML_Char *expected = XCS("yml: something like data\n");
5223 CharData storage;
5224
5225 CharData_Init(&storage);
5226 XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5227 XML_SetUserData(g_parser, &storage);
5228 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5229 == XML_STATUS_ERROR)
5230 xml_failure(g_parser);
5231 CharData_CheckXMLChars(&storage, expected);
5232 }
5233 END_TEST
5234
START_TEST(test_pi_xnl)5235 START_TEST(test_pi_xnl) {
5236 const char *text = "<?xnl nothing like data?><doc/>";
5237 const XML_Char *expected = XCS("xnl: nothing like data\n");
5238 CharData storage;
5239
5240 CharData_Init(&storage);
5241 XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5242 XML_SetUserData(g_parser, &storage);
5243 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5244 == XML_STATUS_ERROR)
5245 xml_failure(g_parser);
5246 CharData_CheckXMLChars(&storage, expected);
5247 }
5248 END_TEST
5249
START_TEST(test_pi_xmm)5250 START_TEST(test_pi_xmm) {
5251 const char *text = "<?xmm everything like data?><doc/>";
5252 const XML_Char *expected = XCS("xmm: everything like data\n");
5253 CharData storage;
5254
5255 CharData_Init(&storage);
5256 XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5257 XML_SetUserData(g_parser, &storage);
5258 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5259 == XML_STATUS_ERROR)
5260 xml_failure(g_parser);
5261 CharData_CheckXMLChars(&storage, expected);
5262 }
5263 END_TEST
5264
START_TEST(test_utf16_pi)5265 START_TEST(test_utf16_pi) {
5266 const char text[] =
5267 /* <?{KHO KHWAI}{CHO CHAN}?>
5268 * where {KHO KHWAI} = U+0E04
5269 * and {CHO CHAN} = U+0E08
5270 */
5271 "<\0?\0\x04\x0e\x08\x0e?\0>\0"
5272 /* <q/> */
5273 "<\0q\0/\0>\0";
5274 #ifdef XML_UNICODE
5275 const XML_Char *expected = XCS("\x0e04\x0e08: \n");
5276 #else
5277 const XML_Char *expected = XCS("\xe0\xb8\x84\xe0\xb8\x88: \n");
5278 #endif
5279 CharData storage;
5280
5281 CharData_Init(&storage);
5282 XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5283 XML_SetUserData(g_parser, &storage);
5284 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5285 == XML_STATUS_ERROR)
5286 xml_failure(g_parser);
5287 CharData_CheckXMLChars(&storage, expected);
5288 }
5289 END_TEST
5290
START_TEST(test_utf16_be_pi)5291 START_TEST(test_utf16_be_pi) {
5292 const char text[] =
5293 /* <?{KHO KHWAI}{CHO CHAN}?>
5294 * where {KHO KHWAI} = U+0E04
5295 * and {CHO CHAN} = U+0E08
5296 */
5297 "\0<\0?\x0e\x04\x0e\x08\0?\0>"
5298 /* <q/> */
5299 "\0<\0q\0/\0>";
5300 #ifdef XML_UNICODE
5301 const XML_Char *expected = XCS("\x0e04\x0e08: \n");
5302 #else
5303 const XML_Char *expected = XCS("\xe0\xb8\x84\xe0\xb8\x88: \n");
5304 #endif
5305 CharData storage;
5306
5307 CharData_Init(&storage);
5308 XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5309 XML_SetUserData(g_parser, &storage);
5310 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5311 == XML_STATUS_ERROR)
5312 xml_failure(g_parser);
5313 CharData_CheckXMLChars(&storage, expected);
5314 }
5315 END_TEST
5316
5317 /* Test that comments can be picked up and translated */
5318 static void XMLCALL
accumulate_comment(void * userData,const XML_Char * data)5319 accumulate_comment(void *userData, const XML_Char *data) {
5320 CharData *storage = (CharData *)userData;
5321
5322 CharData_AppendXMLChars(storage, data, -1);
5323 }
5324
START_TEST(test_utf16_be_comment)5325 START_TEST(test_utf16_be_comment) {
5326 const char text[] =
5327 /* <!-- Comment A --> */
5328 "\0<\0!\0-\0-\0 \0C\0o\0m\0m\0e\0n\0t\0 \0A\0 \0-\0-\0>\0\n"
5329 /* <doc/> */
5330 "\0<\0d\0o\0c\0/\0>";
5331 const XML_Char *expected = XCS(" Comment A ");
5332 CharData storage;
5333
5334 CharData_Init(&storage);
5335 XML_SetCommentHandler(g_parser, accumulate_comment);
5336 XML_SetUserData(g_parser, &storage);
5337 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5338 == XML_STATUS_ERROR)
5339 xml_failure(g_parser);
5340 CharData_CheckXMLChars(&storage, expected);
5341 }
5342 END_TEST
5343
START_TEST(test_utf16_le_comment)5344 START_TEST(test_utf16_le_comment) {
5345 const char text[] =
5346 /* <!-- Comment B --> */
5347 "<\0!\0-\0-\0 \0C\0o\0m\0m\0e\0n\0t\0 \0B\0 \0-\0-\0>\0\n\0"
5348 /* <doc/> */
5349 "<\0d\0o\0c\0/\0>\0";
5350 const XML_Char *expected = XCS(" Comment B ");
5351 CharData storage;
5352
5353 CharData_Init(&storage);
5354 XML_SetCommentHandler(g_parser, accumulate_comment);
5355 XML_SetUserData(g_parser, &storage);
5356 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5357 == XML_STATUS_ERROR)
5358 xml_failure(g_parser);
5359 CharData_CheckXMLChars(&storage, expected);
5360 }
5361 END_TEST
5362
5363 /* Test that the unknown encoding handler with map entries that expect
5364 * conversion but no conversion function is faulted
5365 */
5366 static int XMLCALL
failing_converter(void * data,const char * s)5367 failing_converter(void *data, const char *s) {
5368 UNUSED_P(data);
5369 UNUSED_P(s);
5370 /* Always claim to have failed */
5371 return -1;
5372 }
5373
5374 static int XMLCALL
prefix_converter(void * data,const char * s)5375 prefix_converter(void *data, const char *s) {
5376 UNUSED_P(data);
5377 /* If the first byte is 0xff, raise an error */
5378 if (s[0] == (char)-1)
5379 return -1;
5380 /* Just add the low bits of the first byte to the second */
5381 return (s[1] + (s[0] & 0x7f)) & 0x01ff;
5382 }
5383
5384 static int XMLCALL
MiscEncodingHandler(void * data,const XML_Char * encoding,XML_Encoding * info)5385 MiscEncodingHandler(void *data, const XML_Char *encoding, XML_Encoding *info) {
5386 int i;
5387 int high_map = -2; /* Assume a 2-byte sequence */
5388
5389 if (! xcstrcmp(encoding, XCS("invalid-9"))
5390 || ! xcstrcmp(encoding, XCS("ascii-like"))
5391 || ! xcstrcmp(encoding, XCS("invalid-len"))
5392 || ! xcstrcmp(encoding, XCS("invalid-a"))
5393 || ! xcstrcmp(encoding, XCS("invalid-surrogate"))
5394 || ! xcstrcmp(encoding, XCS("invalid-high")))
5395 high_map = -1;
5396
5397 for (i = 0; i < 128; ++i)
5398 info->map[i] = i;
5399 for (; i < 256; ++i)
5400 info->map[i] = high_map;
5401
5402 /* If required, put an invalid value in the ASCII entries */
5403 if (! xcstrcmp(encoding, XCS("invalid-9")))
5404 info->map[9] = 5;
5405 /* If required, have a top-bit set character starts a 5-byte sequence */
5406 if (! xcstrcmp(encoding, XCS("invalid-len")))
5407 info->map[0x81] = -5;
5408 /* If required, make a top-bit set character a valid ASCII character */
5409 if (! xcstrcmp(encoding, XCS("invalid-a")))
5410 info->map[0x82] = 'a';
5411 /* If required, give a top-bit set character a forbidden value,
5412 * what would otherwise be the first of a surrogate pair.
5413 */
5414 if (! xcstrcmp(encoding, XCS("invalid-surrogate")))
5415 info->map[0x83] = 0xd801;
5416 /* If required, give a top-bit set character too high a value */
5417 if (! xcstrcmp(encoding, XCS("invalid-high")))
5418 info->map[0x84] = 0x010101;
5419
5420 info->data = data;
5421 info->release = NULL;
5422 if (! xcstrcmp(encoding, XCS("failing-conv")))
5423 info->convert = failing_converter;
5424 else if (! xcstrcmp(encoding, XCS("prefix-conv")))
5425 info->convert = prefix_converter;
5426 else
5427 info->convert = NULL;
5428 return XML_STATUS_OK;
5429 }
5430
START_TEST(test_missing_encoding_conversion_fn)5431 START_TEST(test_missing_encoding_conversion_fn) {
5432 const char *text = "<?xml version='1.0' encoding='no-conv'?>\n"
5433 "<doc>\x81</doc>";
5434
5435 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5436 /* MiscEncodingHandler sets up an encoding with every top-bit-set
5437 * character introducing a two-byte sequence. For this, it
5438 * requires a convert function. The above function call doesn't
5439 * pass one through, so when BadEncodingHandler actually gets
5440 * called it should supply an invalid encoding.
5441 */
5442 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5443 "Encoding with missing convert() not faulted");
5444 }
5445 END_TEST
5446
START_TEST(test_failing_encoding_conversion_fn)5447 START_TEST(test_failing_encoding_conversion_fn) {
5448 const char *text = "<?xml version='1.0' encoding='failing-conv'?>\n"
5449 "<doc>\x81</doc>";
5450
5451 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5452 /* BadEncodingHandler sets up an encoding with every top-bit-set
5453 * character introducing a two-byte sequence. For this, it
5454 * requires a convert function. The above function call passes
5455 * one that insists all possible sequences are invalid anyway.
5456 */
5457 expect_failure(text, XML_ERROR_INVALID_TOKEN,
5458 "Encoding with failing convert() not faulted");
5459 }
5460 END_TEST
5461
5462 /* Test unknown encoding conversions */
START_TEST(test_unknown_encoding_success)5463 START_TEST(test_unknown_encoding_success) {
5464 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5465 /* Equivalent to <eoc>Hello, world</eoc> */
5466 "<\x81\x64\x80oc>Hello, world</\x81\x64\x80oc>";
5467
5468 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5469 run_character_check(text, XCS("Hello, world"));
5470 }
5471 END_TEST
5472
5473 /* Test bad name character in unknown encoding */
START_TEST(test_unknown_encoding_bad_name)5474 START_TEST(test_unknown_encoding_bad_name) {
5475 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5476 "<\xff\x64oc>Hello, world</\xff\x64oc>";
5477
5478 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5479 expect_failure(text, XML_ERROR_INVALID_TOKEN,
5480 "Bad name start in unknown encoding not faulted");
5481 }
5482 END_TEST
5483
5484 /* Test bad mid-name character in unknown encoding */
START_TEST(test_unknown_encoding_bad_name_2)5485 START_TEST(test_unknown_encoding_bad_name_2) {
5486 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5487 "<d\xffoc>Hello, world</d\xffoc>";
5488
5489 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5490 expect_failure(text, XML_ERROR_INVALID_TOKEN,
5491 "Bad name in unknown encoding not faulted");
5492 }
5493 END_TEST
5494
5495 /* Test element name that is long enough to fill the conversion buffer
5496 * in an unknown encoding, finishing with an encoded character.
5497 */
START_TEST(test_unknown_encoding_long_name_1)5498 START_TEST(test_unknown_encoding_long_name_1) {
5499 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5500 "<abcdefghabcdefghabcdefghijkl\x80m\x80n\x80o\x80p>"
5501 "Hi"
5502 "</abcdefghabcdefghabcdefghijkl\x80m\x80n\x80o\x80p>";
5503 const XML_Char *expected = XCS("abcdefghabcdefghabcdefghijklmnop");
5504 CharData storage;
5505
5506 CharData_Init(&storage);
5507 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5508 XML_SetStartElementHandler(g_parser, record_element_start_handler);
5509 XML_SetUserData(g_parser, &storage);
5510 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5511 == XML_STATUS_ERROR)
5512 xml_failure(g_parser);
5513 CharData_CheckXMLChars(&storage, expected);
5514 }
5515 END_TEST
5516
5517 /* Test element name that is long enough to fill the conversion buffer
5518 * in an unknown encoding, finishing with an simple character.
5519 */
START_TEST(test_unknown_encoding_long_name_2)5520 START_TEST(test_unknown_encoding_long_name_2) {
5521 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5522 "<abcdefghabcdefghabcdefghijklmnop>"
5523 "Hi"
5524 "</abcdefghabcdefghabcdefghijklmnop>";
5525 const XML_Char *expected = XCS("abcdefghabcdefghabcdefghijklmnop");
5526 CharData storage;
5527
5528 CharData_Init(&storage);
5529 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5530 XML_SetStartElementHandler(g_parser, record_element_start_handler);
5531 XML_SetUserData(g_parser, &storage);
5532 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5533 == XML_STATUS_ERROR)
5534 xml_failure(g_parser);
5535 CharData_CheckXMLChars(&storage, expected);
5536 }
5537 END_TEST
5538
START_TEST(test_invalid_unknown_encoding)5539 START_TEST(test_invalid_unknown_encoding) {
5540 const char *text = "<?xml version='1.0' encoding='invalid-9'?>\n"
5541 "<doc>Hello world</doc>";
5542
5543 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5544 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5545 "Invalid unknown encoding not faulted");
5546 }
5547 END_TEST
5548
START_TEST(test_unknown_ascii_encoding_ok)5549 START_TEST(test_unknown_ascii_encoding_ok) {
5550 const char *text = "<?xml version='1.0' encoding='ascii-like'?>\n"
5551 "<doc>Hello, world</doc>";
5552
5553 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5554 run_character_check(text, XCS("Hello, world"));
5555 }
5556 END_TEST
5557
START_TEST(test_unknown_ascii_encoding_fail)5558 START_TEST(test_unknown_ascii_encoding_fail) {
5559 const char *text = "<?xml version='1.0' encoding='ascii-like'?>\n"
5560 "<doc>Hello, \x80 world</doc>";
5561
5562 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5563 expect_failure(text, XML_ERROR_INVALID_TOKEN,
5564 "Invalid character not faulted");
5565 }
5566 END_TEST
5567
START_TEST(test_unknown_encoding_invalid_length)5568 START_TEST(test_unknown_encoding_invalid_length) {
5569 const char *text = "<?xml version='1.0' encoding='invalid-len'?>\n"
5570 "<doc>Hello, world</doc>";
5571
5572 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5573 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5574 "Invalid unknown encoding not faulted");
5575 }
5576 END_TEST
5577
START_TEST(test_unknown_encoding_invalid_topbit)5578 START_TEST(test_unknown_encoding_invalid_topbit) {
5579 const char *text = "<?xml version='1.0' encoding='invalid-a'?>\n"
5580 "<doc>Hello, world</doc>";
5581
5582 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5583 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5584 "Invalid unknown encoding not faulted");
5585 }
5586 END_TEST
5587
START_TEST(test_unknown_encoding_invalid_surrogate)5588 START_TEST(test_unknown_encoding_invalid_surrogate) {
5589 const char *text = "<?xml version='1.0' encoding='invalid-surrogate'?>\n"
5590 "<doc>Hello, \x82 world</doc>";
5591
5592 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5593 expect_failure(text, XML_ERROR_INVALID_TOKEN,
5594 "Invalid unknown encoding not faulted");
5595 }
5596 END_TEST
5597
START_TEST(test_unknown_encoding_invalid_high)5598 START_TEST(test_unknown_encoding_invalid_high) {
5599 const char *text = "<?xml version='1.0' encoding='invalid-high'?>\n"
5600 "<doc>Hello, world</doc>";
5601
5602 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5603 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5604 "Invalid unknown encoding not faulted");
5605 }
5606 END_TEST
5607
START_TEST(test_unknown_encoding_invalid_attr_value)5608 START_TEST(test_unknown_encoding_invalid_attr_value) {
5609 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5610 "<doc attr='\xff\x30'/>";
5611
5612 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5613 expect_failure(text, XML_ERROR_INVALID_TOKEN,
5614 "Invalid attribute valid not faulted");
5615 }
5616 END_TEST
5617
5618 /* Test an external entity parser set to use latin-1 detects UTF-16
5619 * BOMs correctly.
5620 */
5621 enum ee_parse_flags { EE_PARSE_NONE = 0x00, EE_PARSE_FULL_BUFFER = 0x01 };
5622
5623 typedef struct ExtTest2 {
5624 const char *parse_text;
5625 int parse_len;
5626 const XML_Char *encoding;
5627 CharData *storage;
5628 enum ee_parse_flags flags;
5629 } ExtTest2;
5630
5631 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)5632 external_entity_loader2(XML_Parser parser, const XML_Char *context,
5633 const XML_Char *base, const XML_Char *systemId,
5634 const XML_Char *publicId) {
5635 ExtTest2 *test_data = (ExtTest2 *)XML_GetUserData(parser);
5636 XML_Parser extparser;
5637
5638 UNUSED_P(base);
5639 UNUSED_P(systemId);
5640 UNUSED_P(publicId);
5641 extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
5642 if (extparser == NULL)
5643 fail("Coulr not create external entity parser");
5644 if (test_data->encoding != NULL) {
5645 if (! XML_SetEncoding(extparser, test_data->encoding))
5646 fail("XML_SetEncoding() ignored for external entity");
5647 }
5648 if (test_data->flags & EE_PARSE_FULL_BUFFER) {
5649 if (XML_Parse(extparser, test_data->parse_text, test_data->parse_len,
5650 XML_TRUE)
5651 == XML_STATUS_ERROR) {
5652 xml_failure(extparser);
5653 }
5654 } else if (_XML_Parse_SINGLE_BYTES(extparser, test_data->parse_text,
5655 test_data->parse_len, XML_TRUE)
5656 == XML_STATUS_ERROR) {
5657 xml_failure(extparser);
5658 }
5659
5660 XML_ParserFree(extparser);
5661 return XML_STATUS_OK;
5662 }
5663
5664 /* Test that UTF-16 BOM does not select UTF-16 given explicit encoding */
5665 static void XMLCALL
ext2_accumulate_characters(void * userData,const XML_Char * s,int len)5666 ext2_accumulate_characters(void *userData, const XML_Char *s, int len) {
5667 ExtTest2 *test_data = (ExtTest2 *)userData;
5668 accumulate_characters(test_data->storage, s, len);
5669 }
5670
START_TEST(test_ext_entity_latin1_utf16le_bom)5671 START_TEST(test_ext_entity_latin1_utf16le_bom) {
5672 const char *text = "<!DOCTYPE doc [\n"
5673 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5674 "]>\n"
5675 "<doc>&en;</doc>";
5676 ExtTest2 test_data
5677 = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */
5678 /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn,
5679 * 0x4c = L and 0x20 is a space
5680 */
5681 "\xff\xfe\x4c\x20", 4, XCS("iso-8859-1"), NULL, EE_PARSE_NONE};
5682 #ifdef XML_UNICODE
5683 const XML_Char *expected = XCS("\x00ff\x00feL ");
5684 #else
5685 /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */
5686 const XML_Char *expected = XCS("\xc3\xbf\xc3\xbeL ");
5687 #endif
5688 CharData storage;
5689
5690 CharData_Init(&storage);
5691 test_data.storage = &storage;
5692 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5693 XML_SetUserData(g_parser, &test_data);
5694 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5695 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5696 == XML_STATUS_ERROR)
5697 xml_failure(g_parser);
5698 CharData_CheckXMLChars(&storage, expected);
5699 }
5700 END_TEST
5701
START_TEST(test_ext_entity_latin1_utf16be_bom)5702 START_TEST(test_ext_entity_latin1_utf16be_bom) {
5703 const char *text = "<!DOCTYPE doc [\n"
5704 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5705 "]>\n"
5706 "<doc>&en;</doc>";
5707 ExtTest2 test_data
5708 = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */
5709 /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn,
5710 * 0x4c = L and 0x20 is a space
5711 */
5712 "\xfe\xff\x20\x4c", 4, XCS("iso-8859-1"), NULL, EE_PARSE_NONE};
5713 #ifdef XML_UNICODE
5714 const XML_Char *expected = XCS("\x00fe\x00ff L");
5715 #else
5716 /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */
5717 const XML_Char *expected = XCS("\xc3\xbe\xc3\xbf L");
5718 #endif
5719 CharData storage;
5720
5721 CharData_Init(&storage);
5722 test_data.storage = &storage;
5723 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5724 XML_SetUserData(g_parser, &test_data);
5725 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5726 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5727 == XML_STATUS_ERROR)
5728 xml_failure(g_parser);
5729 CharData_CheckXMLChars(&storage, expected);
5730 }
5731 END_TEST
5732
5733 /* Parsing the full buffer rather than a byte at a time makes a
5734 * difference to the encoding scanning code, so repeat the above tests
5735 * without breaking them down by byte.
5736 */
START_TEST(test_ext_entity_latin1_utf16le_bom2)5737 START_TEST(test_ext_entity_latin1_utf16le_bom2) {
5738 const char *text = "<!DOCTYPE doc [\n"
5739 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5740 "]>\n"
5741 "<doc>&en;</doc>";
5742 ExtTest2 test_data
5743 = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */
5744 /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn,
5745 * 0x4c = L and 0x20 is a space
5746 */
5747 "\xff\xfe\x4c\x20", 4, XCS("iso-8859-1"), NULL, EE_PARSE_FULL_BUFFER};
5748 #ifdef XML_UNICODE
5749 const XML_Char *expected = XCS("\x00ff\x00feL ");
5750 #else
5751 /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */
5752 const XML_Char *expected = XCS("\xc3\xbf\xc3\xbeL ");
5753 #endif
5754 CharData storage;
5755
5756 CharData_Init(&storage);
5757 test_data.storage = &storage;
5758 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5759 XML_SetUserData(g_parser, &test_data);
5760 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5761 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
5762 == XML_STATUS_ERROR)
5763 xml_failure(g_parser);
5764 CharData_CheckXMLChars(&storage, expected);
5765 }
5766 END_TEST
5767
START_TEST(test_ext_entity_latin1_utf16be_bom2)5768 START_TEST(test_ext_entity_latin1_utf16be_bom2) {
5769 const char *text = "<!DOCTYPE doc [\n"
5770 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5771 "]>\n"
5772 "<doc>&en;</doc>";
5773 ExtTest2 test_data
5774 = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */
5775 /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn,
5776 * 0x4c = L and 0x20 is a space
5777 */
5778 "\xfe\xff\x20\x4c", 4, XCS("iso-8859-1"), NULL, EE_PARSE_FULL_BUFFER};
5779 #ifdef XML_UNICODE
5780 const XML_Char *expected = XCS("\x00fe\x00ff L");
5781 #else
5782 /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */
5783 const XML_Char *expected = "\xc3\xbe\xc3\xbf L";
5784 #endif
5785 CharData storage;
5786
5787 CharData_Init(&storage);
5788 test_data.storage = &storage;
5789 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5790 XML_SetUserData(g_parser, &test_data);
5791 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5792 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
5793 == XML_STATUS_ERROR)
5794 xml_failure(g_parser);
5795 CharData_CheckXMLChars(&storage, expected);
5796 }
5797 END_TEST
5798
5799 /* Test little-endian UTF-16 given an explicit big-endian encoding */
START_TEST(test_ext_entity_utf16_be)5800 START_TEST(test_ext_entity_utf16_be) {
5801 const char *text = "<!DOCTYPE doc [\n"
5802 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5803 "]>\n"
5804 "<doc>&en;</doc>";
5805 ExtTest2 test_data
5806 = {"<\0e\0/\0>\0", 8, XCS("utf-16be"), NULL, EE_PARSE_NONE};
5807 #ifdef XML_UNICODE
5808 const XML_Char *expected = XCS("\x3c00\x6500\x2f00\x3e00");
5809 #else
5810 const XML_Char *expected = XCS("\xe3\xb0\x80" /* U+3C00 */
5811 "\xe6\x94\x80" /* U+6500 */
5812 "\xe2\xbc\x80" /* U+2F00 */
5813 "\xe3\xb8\x80"); /* U+3E00 */
5814 #endif
5815 CharData storage;
5816
5817 CharData_Init(&storage);
5818 test_data.storage = &storage;
5819 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5820 XML_SetUserData(g_parser, &test_data);
5821 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5822 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5823 == XML_STATUS_ERROR)
5824 xml_failure(g_parser);
5825 CharData_CheckXMLChars(&storage, expected);
5826 }
5827 END_TEST
5828
5829 /* Test big-endian UTF-16 given an explicit little-endian encoding */
START_TEST(test_ext_entity_utf16_le)5830 START_TEST(test_ext_entity_utf16_le) {
5831 const char *text = "<!DOCTYPE doc [\n"
5832 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5833 "]>\n"
5834 "<doc>&en;</doc>";
5835 ExtTest2 test_data
5836 = {"\0<\0e\0/\0>", 8, XCS("utf-16le"), NULL, EE_PARSE_NONE};
5837 #ifdef XML_UNICODE
5838 const XML_Char *expected = XCS("\x3c00\x6500\x2f00\x3e00");
5839 #else
5840 const XML_Char *expected = XCS("\xe3\xb0\x80" /* U+3C00 */
5841 "\xe6\x94\x80" /* U+6500 */
5842 "\xe2\xbc\x80" /* U+2F00 */
5843 "\xe3\xb8\x80"); /* U+3E00 */
5844 #endif
5845 CharData storage;
5846
5847 CharData_Init(&storage);
5848 test_data.storage = &storage;
5849 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5850 XML_SetUserData(g_parser, &test_data);
5851 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5852 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5853 == XML_STATUS_ERROR)
5854 xml_failure(g_parser);
5855 CharData_CheckXMLChars(&storage, expected);
5856 }
5857 END_TEST
5858
5859 /* Test little-endian UTF-16 given no explicit encoding.
5860 * The existing default encoding (UTF-8) is assumed to hold without a
5861 * BOM to contradict it, so the entity value will in fact provoke an
5862 * error because 0x00 is not a valid XML character. We parse the
5863 * whole buffer in one go rather than feeding it in byte by byte to
5864 * exercise different code paths in the initial scanning routines.
5865 */
5866 typedef struct ExtFaults2 {
5867 const char *parse_text;
5868 int parse_len;
5869 const char *fail_text;
5870 const XML_Char *encoding;
5871 enum XML_Error error;
5872 } ExtFaults2;
5873
5874 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)5875 external_entity_faulter2(XML_Parser parser, const XML_Char *context,
5876 const XML_Char *base, const XML_Char *systemId,
5877 const XML_Char *publicId) {
5878 ExtFaults2 *test_data = (ExtFaults2 *)XML_GetUserData(parser);
5879 XML_Parser extparser;
5880
5881 UNUSED_P(base);
5882 UNUSED_P(systemId);
5883 UNUSED_P(publicId);
5884 extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
5885 if (extparser == NULL)
5886 fail("Could not create external entity parser");
5887 if (test_data->encoding != NULL) {
5888 if (! XML_SetEncoding(extparser, test_data->encoding))
5889 fail("XML_SetEncoding() ignored for external entity");
5890 }
5891 if (XML_Parse(extparser, test_data->parse_text, test_data->parse_len,
5892 XML_TRUE)
5893 != XML_STATUS_ERROR)
5894 fail(test_data->fail_text);
5895 if (XML_GetErrorCode(extparser) != test_data->error)
5896 xml_failure(extparser);
5897
5898 XML_ParserFree(extparser);
5899 return XML_STATUS_ERROR;
5900 }
5901
START_TEST(test_ext_entity_utf16_unknown)5902 START_TEST(test_ext_entity_utf16_unknown) {
5903 const char *text = "<!DOCTYPE doc [\n"
5904 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5905 "]>\n"
5906 "<doc>&en;</doc>";
5907 ExtFaults2 test_data
5908 = {"a\0b\0c\0", 6, "Invalid character in entity not faulted", NULL,
5909 XML_ERROR_INVALID_TOKEN};
5910
5911 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter2);
5912 XML_SetUserData(g_parser, &test_data);
5913 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
5914 "Invalid character should not have been accepted");
5915 }
5916 END_TEST
5917
5918 /* Test not-quite-UTF-8 BOM (0xEF 0xBB 0xBF) */
START_TEST(test_ext_entity_utf8_non_bom)5919 START_TEST(test_ext_entity_utf8_non_bom) {
5920 const char *text = "<!DOCTYPE doc [\n"
5921 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5922 "]>\n"
5923 "<doc>&en;</doc>";
5924 ExtTest2 test_data
5925 = {"\xef\xbb\x80", /* Arabic letter DAD medial form, U+FEC0 */
5926 3, NULL, NULL, EE_PARSE_NONE};
5927 #ifdef XML_UNICODE
5928 const XML_Char *expected = XCS("\xfec0");
5929 #else
5930 const XML_Char *expected = XCS("\xef\xbb\x80");
5931 #endif
5932 CharData storage;
5933
5934 CharData_Init(&storage);
5935 test_data.storage = &storage;
5936 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5937 XML_SetUserData(g_parser, &test_data);
5938 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5939 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5940 == XML_STATUS_ERROR)
5941 xml_failure(g_parser);
5942 CharData_CheckXMLChars(&storage, expected);
5943 }
5944 END_TEST
5945
5946 /* Test that UTF-8 in a CDATA section is correctly passed through */
START_TEST(test_utf8_in_cdata_section)5947 START_TEST(test_utf8_in_cdata_section) {
5948 const char *text = "<doc><![CDATA[one \xc3\xa9 two]]></doc>";
5949 #ifdef XML_UNICODE
5950 const XML_Char *expected = XCS("one \x00e9 two");
5951 #else
5952 const XML_Char *expected = XCS("one \xc3\xa9 two");
5953 #endif
5954
5955 run_character_check(text, expected);
5956 }
5957 END_TEST
5958
5959 /* Test that little-endian UTF-16 in a CDATA section is handled */
START_TEST(test_utf8_in_cdata_section_2)5960 START_TEST(test_utf8_in_cdata_section_2) {
5961 const char *text = "<doc><![CDATA[\xc3\xa9]\xc3\xa9two]]></doc>";
5962 #ifdef XML_UNICODE
5963 const XML_Char *expected = XCS("\x00e9]\x00e9two");
5964 #else
5965 const XML_Char *expected = XCS("\xc3\xa9]\xc3\xa9two");
5966 #endif
5967
5968 run_character_check(text, expected);
5969 }
5970 END_TEST
5971
5972 /* Test trailing spaces in elements are accepted */
5973 static void XMLCALL
record_element_end_handler(void * userData,const XML_Char * name)5974 record_element_end_handler(void *userData, const XML_Char *name) {
5975 CharData *storage = (CharData *)userData;
5976
5977 CharData_AppendXMLChars(storage, XCS("/"), 1);
5978 CharData_AppendXMLChars(storage, name, -1);
5979 }
5980
START_TEST(test_trailing_spaces_in_elements)5981 START_TEST(test_trailing_spaces_in_elements) {
5982 const char *text = "<doc >Hi</doc >";
5983 const XML_Char *expected = XCS("doc/doc");
5984 CharData storage;
5985
5986 CharData_Init(&storage);
5987 XML_SetElementHandler(g_parser, record_element_start_handler,
5988 record_element_end_handler);
5989 XML_SetUserData(g_parser, &storage);
5990 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5991 == XML_STATUS_ERROR)
5992 xml_failure(g_parser);
5993 CharData_CheckXMLChars(&storage, expected);
5994 }
5995 END_TEST
5996
START_TEST(test_utf16_attribute)5997 START_TEST(test_utf16_attribute) {
5998 const char text[] =
5999 /* <d {KHO KHWAI}{CHO CHAN}='a'/>
6000 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
6001 * and {CHO CHAN} = U+0E08 = 0xe0 0xb8 0x88 in UTF-8
6002 */
6003 "<\0d\0 \0\x04\x0e\x08\x0e=\0'\0a\0'\0/\0>\0";
6004 const XML_Char *expected = XCS("a");
6005 CharData storage;
6006
6007 CharData_Init(&storage);
6008 XML_SetStartElementHandler(g_parser, accumulate_attribute);
6009 XML_SetUserData(g_parser, &storage);
6010 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6011 == XML_STATUS_ERROR)
6012 xml_failure(g_parser);
6013 CharData_CheckXMLChars(&storage, expected);
6014 }
6015 END_TEST
6016
START_TEST(test_utf16_second_attr)6017 START_TEST(test_utf16_second_attr) {
6018 /* <d a='1' {KHO KHWAI}{CHO CHAN}='2'/>
6019 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
6020 * and {CHO CHAN} = U+0E08 = 0xe0 0xb8 0x88 in UTF-8
6021 */
6022 const char text[] = "<\0d\0 \0a\0=\0'\0\x31\0'\0 \0"
6023 "\x04\x0e\x08\x0e=\0'\0\x32\0'\0/\0>\0";
6024 const XML_Char *expected = XCS("1");
6025 CharData storage;
6026
6027 CharData_Init(&storage);
6028 XML_SetStartElementHandler(g_parser, accumulate_attribute);
6029 XML_SetUserData(g_parser, &storage);
6030 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6031 == XML_STATUS_ERROR)
6032 xml_failure(g_parser);
6033 CharData_CheckXMLChars(&storage, expected);
6034 }
6035 END_TEST
6036
START_TEST(test_attr_after_solidus)6037 START_TEST(test_attr_after_solidus) {
6038 const char *text = "<doc attr1='a' / attr2='b'>";
6039
6040 expect_failure(text, XML_ERROR_INVALID_TOKEN, "Misplaced / not faulted");
6041 }
6042 END_TEST
6043
6044 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)6045 accumulate_entity_decl(void *userData, const XML_Char *entityName,
6046 int is_parameter_entity, const XML_Char *value,
6047 int value_length, const XML_Char *base,
6048 const XML_Char *systemId, const XML_Char *publicId,
6049 const XML_Char *notationName) {
6050 CharData *storage = (CharData *)userData;
6051
6052 UNUSED_P(is_parameter_entity);
6053 UNUSED_P(base);
6054 UNUSED_P(systemId);
6055 UNUSED_P(publicId);
6056 UNUSED_P(notationName);
6057 CharData_AppendXMLChars(storage, entityName, -1);
6058 CharData_AppendXMLChars(storage, XCS("="), 1);
6059 CharData_AppendXMLChars(storage, value, value_length);
6060 CharData_AppendXMLChars(storage, XCS("\n"), 1);
6061 }
6062
START_TEST(test_utf16_pe)6063 START_TEST(test_utf16_pe) {
6064 /* <!DOCTYPE doc [
6065 * <!ENTITY % {KHO KHWAI}{CHO CHAN} '<!ELEMENT doc (#PCDATA)>'>
6066 * %{KHO KHWAI}{CHO CHAN};
6067 * ]>
6068 * <doc></doc>
6069 *
6070 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
6071 * and {CHO CHAN} = U+0E08 = 0xe0 0xb8 0x88 in UTF-8
6072 */
6073 const char text[] = "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0\n"
6074 "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \x0e\x04\x0e\x08\0 "
6075 "\0'\0<\0!\0E\0L\0E\0M\0E\0N\0T\0 "
6076 "\0d\0o\0c\0 \0(\0#\0P\0C\0D\0A\0T\0A\0)\0>\0'\0>\0\n"
6077 "\0%\x0e\x04\x0e\x08\0;\0\n"
6078 "\0]\0>\0\n"
6079 "\0<\0d\0o\0c\0>\0<\0/\0d\0o\0c\0>";
6080 #ifdef XML_UNICODE
6081 const XML_Char *expected = XCS("\x0e04\x0e08=<!ELEMENT doc (#PCDATA)>\n");
6082 #else
6083 const XML_Char *expected
6084 = XCS("\xe0\xb8\x84\xe0\xb8\x88=<!ELEMENT doc (#PCDATA)>\n");
6085 #endif
6086 CharData storage;
6087
6088 CharData_Init(&storage);
6089 XML_SetUserData(g_parser, &storage);
6090 XML_SetEntityDeclHandler(g_parser, accumulate_entity_decl);
6091 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6092 == XML_STATUS_ERROR)
6093 xml_failure(g_parser);
6094 CharData_CheckXMLChars(&storage, expected);
6095 }
6096 END_TEST
6097
6098 /* Test that duff attribute description keywords are rejected */
START_TEST(test_bad_attr_desc_keyword)6099 START_TEST(test_bad_attr_desc_keyword) {
6100 const char *text = "<!DOCTYPE doc [\n"
6101 " <!ATTLIST doc attr CDATA #!IMPLIED>\n"
6102 "]>\n"
6103 "<doc />";
6104
6105 expect_failure(text, XML_ERROR_INVALID_TOKEN,
6106 "Bad keyword !IMPLIED not faulted");
6107 }
6108 END_TEST
6109
6110 /* Test that an invalid attribute description keyword consisting of
6111 * UTF-16 characters with their top bytes non-zero are correctly
6112 * faulted
6113 */
START_TEST(test_bad_attr_desc_keyword_utf16)6114 START_TEST(test_bad_attr_desc_keyword_utf16) {
6115 /* <!DOCTYPE d [
6116 * <!ATTLIST d a CDATA #{KHO KHWAI}{CHO CHAN}>
6117 * ]><d/>
6118 *
6119 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
6120 * and {CHO CHAN} = U+0E08 = 0xe0 0xb8 0x88 in UTF-8
6121 */
6122 const char text[]
6123 = "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n"
6124 "\0<\0!\0A\0T\0T\0L\0I\0S\0T\0 \0d\0 \0a\0 \0C\0D\0A\0T\0A\0 "
6125 "\0#\x0e\x04\x0e\x08\0>\0\n"
6126 "\0]\0>\0<\0d\0/\0>";
6127
6128 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6129 != XML_STATUS_ERROR)
6130 fail("Invalid UTF16 attribute keyword not faulted");
6131 if (XML_GetErrorCode(g_parser) != XML_ERROR_SYNTAX)
6132 xml_failure(g_parser);
6133 }
6134 END_TEST
6135
6136 /* Test that invalid syntax in a <!DOCTYPE> is rejected. Do this
6137 * using prefix-encoding (see above) to trigger specific code paths
6138 */
START_TEST(test_bad_doctype)6139 START_TEST(test_bad_doctype) {
6140 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
6141 "<!DOCTYPE doc [ \x80\x44 ]><doc/>";
6142
6143 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
6144 expect_failure(text, XML_ERROR_SYNTAX,
6145 "Invalid bytes in DOCTYPE not faulted");
6146 }
6147 END_TEST
6148
START_TEST(test_bad_doctype_utf16)6149 START_TEST(test_bad_doctype_utf16) {
6150 const char text[] =
6151 /* <!DOCTYPE doc [ \x06f2 ]><doc/>
6152 *
6153 * U+06F2 = EXTENDED ARABIC-INDIC DIGIT TWO, a valid number
6154 * (name character) but not a valid letter (name start character)
6155 */
6156 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0 "
6157 "\x06\xf2"
6158 "\0 \0]\0>\0<\0d\0o\0c\0/\0>";
6159
6160 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6161 != XML_STATUS_ERROR)
6162 fail("Invalid bytes in DOCTYPE not faulted");
6163 if (XML_GetErrorCode(g_parser) != XML_ERROR_SYNTAX)
6164 xml_failure(g_parser);
6165 }
6166 END_TEST
6167
START_TEST(test_bad_doctype_plus)6168 START_TEST(test_bad_doctype_plus) {
6169 const char *text = "<!DOCTYPE 1+ [ <!ENTITY foo 'bar'> ]>\n"
6170 "<1+>&foo;</1+>";
6171
6172 expect_failure(text, XML_ERROR_INVALID_TOKEN,
6173 "'+' in document name not faulted");
6174 }
6175 END_TEST
6176
START_TEST(test_bad_doctype_star)6177 START_TEST(test_bad_doctype_star) {
6178 const char *text = "<!DOCTYPE 1* [ <!ENTITY foo 'bar'> ]>\n"
6179 "<1*>&foo;</1*>";
6180
6181 expect_failure(text, XML_ERROR_INVALID_TOKEN,
6182 "'*' in document name not faulted");
6183 }
6184 END_TEST
6185
START_TEST(test_bad_doctype_query)6186 START_TEST(test_bad_doctype_query) {
6187 const char *text = "<!DOCTYPE 1? [ <!ENTITY foo 'bar'> ]>\n"
6188 "<1?>&foo;</1?>";
6189
6190 expect_failure(text, XML_ERROR_INVALID_TOKEN,
6191 "'?' in document name not faulted");
6192 }
6193 END_TEST
6194
START_TEST(test_unknown_encoding_bad_ignore)6195 START_TEST(test_unknown_encoding_bad_ignore) {
6196 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>"
6197 "<!DOCTYPE doc SYSTEM 'foo'>"
6198 "<doc><e>&entity;</e></doc>";
6199 ExtFaults fault = {"<![IGNORE[<!ELEMENT \xffG (#PCDATA)*>]]>",
6200 "Invalid character not faulted", XCS("prefix-conv"),
6201 XML_ERROR_INVALID_TOKEN};
6202
6203 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
6204 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6205 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
6206 XML_SetUserData(g_parser, &fault);
6207 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
6208 "Bad IGNORE section with unknown encoding not failed");
6209 }
6210 END_TEST
6211
START_TEST(test_entity_in_utf16_be_attr)6212 START_TEST(test_entity_in_utf16_be_attr) {
6213 const char text[] =
6214 /* <e a='ä ä'></e> */
6215 "\0<\0e\0 \0a\0=\0'\0&\0#\0\x32\0\x32\0\x38\0;\0 "
6216 "\0&\0#\0x\0\x30\0\x30\0E\0\x34\0;\0'\0>\0<\0/\0e\0>";
6217 #ifdef XML_UNICODE
6218 const XML_Char *expected = XCS("\x00e4 \x00e4");
6219 #else
6220 const XML_Char *expected = XCS("\xc3\xa4 \xc3\xa4");
6221 #endif
6222 CharData storage;
6223
6224 CharData_Init(&storage);
6225 XML_SetUserData(g_parser, &storage);
6226 XML_SetStartElementHandler(g_parser, accumulate_attribute);
6227 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6228 == XML_STATUS_ERROR)
6229 xml_failure(g_parser);
6230 CharData_CheckXMLChars(&storage, expected);
6231 }
6232 END_TEST
6233
START_TEST(test_entity_in_utf16_le_attr)6234 START_TEST(test_entity_in_utf16_le_attr) {
6235 const char text[] =
6236 /* <e a='ä ä'></e> */
6237 "<\0e\0 \0a\0=\0'\0&\0#\0\x32\0\x32\0\x38\0;\0 \0"
6238 "&\0#\0x\0\x30\0\x30\0E\0\x34\0;\0'\0>\0<\0/\0e\0>\0";
6239 #ifdef XML_UNICODE
6240 const XML_Char *expected = XCS("\x00e4 \x00e4");
6241 #else
6242 const XML_Char *expected = XCS("\xc3\xa4 \xc3\xa4");
6243 #endif
6244 CharData storage;
6245
6246 CharData_Init(&storage);
6247 XML_SetUserData(g_parser, &storage);
6248 XML_SetStartElementHandler(g_parser, accumulate_attribute);
6249 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6250 == XML_STATUS_ERROR)
6251 xml_failure(g_parser);
6252 CharData_CheckXMLChars(&storage, expected);
6253 }
6254 END_TEST
6255
START_TEST(test_entity_public_utf16_be)6256 START_TEST(test_entity_public_utf16_be) {
6257 const char text[] =
6258 /* <!DOCTYPE d [ */
6259 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n"
6260 /* <!ENTITY % e PUBLIC 'foo' 'bar.ent'> */
6261 "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \0e\0 \0P\0U\0B\0L\0I\0C\0 "
6262 "\0'\0f\0o\0o\0'\0 \0'\0b\0a\0r\0.\0e\0n\0t\0'\0>\0\n"
6263 /* %e; */
6264 "\0%\0e\0;\0\n"
6265 /* ]> */
6266 "\0]\0>\0\n"
6267 /* <d>&j;</d> */
6268 "\0<\0d\0>\0&\0j\0;\0<\0/\0d\0>";
6269 ExtTest2 test_data = {/* <!ENTITY j 'baz'> */
6270 "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0j\0 \0'\0b\0a\0z\0'\0>",
6271 34, NULL, NULL, EE_PARSE_NONE};
6272 const XML_Char *expected = XCS("baz");
6273 CharData storage;
6274
6275 CharData_Init(&storage);
6276 test_data.storage = &storage;
6277 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6278 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
6279 XML_SetUserData(g_parser, &test_data);
6280 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
6281 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6282 == XML_STATUS_ERROR)
6283 xml_failure(g_parser);
6284 CharData_CheckXMLChars(&storage, expected);
6285 }
6286 END_TEST
6287
START_TEST(test_entity_public_utf16_le)6288 START_TEST(test_entity_public_utf16_le) {
6289 const char text[] =
6290 /* <!DOCTYPE d [ */
6291 "<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n\0"
6292 /* <!ENTITY % e PUBLIC 'foo' 'bar.ent'> */
6293 "<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \0e\0 \0P\0U\0B\0L\0I\0C\0 \0"
6294 "'\0f\0o\0o\0'\0 \0'\0b\0a\0r\0.\0e\0n\0t\0'\0>\0\n\0"
6295 /* %e; */
6296 "%\0e\0;\0\n\0"
6297 /* ]> */
6298 "]\0>\0\n\0"
6299 /* <d>&j;</d> */
6300 "<\0d\0>\0&\0j\0;\0<\0/\0d\0>\0";
6301 ExtTest2 test_data = {/* <!ENTITY j 'baz'> */
6302 "<\0!\0E\0N\0T\0I\0T\0Y\0 \0j\0 \0'\0b\0a\0z\0'\0>\0",
6303 34, NULL, NULL, EE_PARSE_NONE};
6304 const XML_Char *expected = XCS("baz");
6305 CharData storage;
6306
6307 CharData_Init(&storage);
6308 test_data.storage = &storage;
6309 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6310 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
6311 XML_SetUserData(g_parser, &test_data);
6312 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
6313 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6314 == XML_STATUS_ERROR)
6315 xml_failure(g_parser);
6316 CharData_CheckXMLChars(&storage, expected);
6317 }
6318 END_TEST
6319
6320 /* Test that a doctype with neither an internal nor external subset is
6321 * faulted
6322 */
START_TEST(test_short_doctype)6323 START_TEST(test_short_doctype) {
6324 const char *text = "<!DOCTYPE doc></doc>";
6325 expect_failure(text, XML_ERROR_INVALID_TOKEN,
6326 "DOCTYPE without subset not rejected");
6327 }
6328 END_TEST
6329
START_TEST(test_short_doctype_2)6330 START_TEST(test_short_doctype_2) {
6331 const char *text = "<!DOCTYPE doc PUBLIC></doc>";
6332 expect_failure(text, XML_ERROR_SYNTAX,
6333 "DOCTYPE without Public ID not rejected");
6334 }
6335 END_TEST
6336
START_TEST(test_short_doctype_3)6337 START_TEST(test_short_doctype_3) {
6338 const char *text = "<!DOCTYPE doc SYSTEM></doc>";
6339 expect_failure(text, XML_ERROR_SYNTAX,
6340 "DOCTYPE without System ID not rejected");
6341 }
6342 END_TEST
6343
START_TEST(test_long_doctype)6344 START_TEST(test_long_doctype) {
6345 const char *text = "<!DOCTYPE doc PUBLIC 'foo' 'bar' 'baz'></doc>";
6346 expect_failure(text, XML_ERROR_SYNTAX, "DOCTYPE with extra ID not rejected");
6347 }
6348 END_TEST
6349
START_TEST(test_bad_entity)6350 START_TEST(test_bad_entity) {
6351 const char *text = "<!DOCTYPE doc [\n"
6352 " <!ENTITY foo PUBLIC>\n"
6353 "]>\n"
6354 "<doc/>";
6355 expect_failure(text, XML_ERROR_SYNTAX,
6356 "ENTITY without Public ID is not rejected");
6357 }
6358 END_TEST
6359
6360 /* Test unquoted value is faulted */
START_TEST(test_bad_entity_2)6361 START_TEST(test_bad_entity_2) {
6362 const char *text = "<!DOCTYPE doc [\n"
6363 " <!ENTITY % foo bar>\n"
6364 "]>\n"
6365 "<doc/>";
6366 expect_failure(text, XML_ERROR_SYNTAX,
6367 "ENTITY without Public ID is not rejected");
6368 }
6369 END_TEST
6370
START_TEST(test_bad_entity_3)6371 START_TEST(test_bad_entity_3) {
6372 const char *text = "<!DOCTYPE doc [\n"
6373 " <!ENTITY % foo PUBLIC>\n"
6374 "]>\n"
6375 "<doc/>";
6376 expect_failure(text, XML_ERROR_SYNTAX,
6377 "Parameter ENTITY without Public ID is not rejected");
6378 }
6379 END_TEST
6380
START_TEST(test_bad_entity_4)6381 START_TEST(test_bad_entity_4) {
6382 const char *text = "<!DOCTYPE doc [\n"
6383 " <!ENTITY % foo SYSTEM>\n"
6384 "]>\n"
6385 "<doc/>";
6386 expect_failure(text, XML_ERROR_SYNTAX,
6387 "Parameter ENTITY without Public ID is not rejected");
6388 }
6389 END_TEST
6390
START_TEST(test_bad_notation)6391 START_TEST(test_bad_notation) {
6392 const char *text = "<!DOCTYPE doc [\n"
6393 " <!NOTATION n SYSTEM>\n"
6394 "]>\n"
6395 "<doc/>";
6396 expect_failure(text, XML_ERROR_SYNTAX,
6397 "Notation without System ID is not rejected");
6398 }
6399 END_TEST
6400
6401 /* Test for issue #11, wrongly suppressed default handler */
6402 typedef struct default_check {
6403 const XML_Char *expected;
6404 const int expectedLen;
6405 XML_Bool seen;
6406 } DefaultCheck;
6407
6408 static void XMLCALL
checking_default_handler(void * userData,const XML_Char * s,int len)6409 checking_default_handler(void *userData, const XML_Char *s, int len) {
6410 DefaultCheck *data = (DefaultCheck *)userData;
6411 int i;
6412
6413 for (i = 0; data[i].expected != NULL; i++) {
6414 if (data[i].expectedLen == len
6415 && ! memcmp(data[i].expected, s, len * sizeof(XML_Char))) {
6416 data[i].seen = XML_TRUE;
6417 break;
6418 }
6419 }
6420 }
6421
START_TEST(test_default_doctype_handler)6422 START_TEST(test_default_doctype_handler) {
6423 const char *text = "<!DOCTYPE doc PUBLIC 'pubname' 'test.dtd' [\n"
6424 " <!ENTITY foo 'bar'>\n"
6425 "]>\n"
6426 "<doc>&foo;</doc>";
6427 DefaultCheck test_data[] = {{XCS("'pubname'"), 9, XML_FALSE},
6428 {XCS("'test.dtd'"), 10, XML_FALSE},
6429 {NULL, 0, XML_FALSE}};
6430 int i;
6431
6432 XML_SetUserData(g_parser, &test_data);
6433 XML_SetDefaultHandler(g_parser, checking_default_handler);
6434 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
6435 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6436 == XML_STATUS_ERROR)
6437 xml_failure(g_parser);
6438 for (i = 0; test_data[i].expected != NULL; i++)
6439 if (! test_data[i].seen)
6440 fail("Default handler not run for public !DOCTYPE");
6441 }
6442 END_TEST
6443
START_TEST(test_empty_element_abort)6444 START_TEST(test_empty_element_abort) {
6445 const char *text = "<abort/>";
6446
6447 XML_SetStartElementHandler(g_parser, start_element_suspender);
6448 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6449 != XML_STATUS_ERROR)
6450 fail("Expected to error on abort");
6451 }
6452 END_TEST
6453
6454 /*
6455 * Namespaces tests.
6456 */
6457
6458 static void
namespace_setup(void)6459 namespace_setup(void) {
6460 g_parser = XML_ParserCreateNS(NULL, XCS(' '));
6461 if (g_parser == NULL)
6462 fail("Parser not created.");
6463 }
6464
6465 static void
namespace_teardown(void)6466 namespace_teardown(void) {
6467 basic_teardown();
6468 }
6469
6470 /* Check that an element name and attribute name match the expected values.
6471 The expected values are passed as an array reference of string pointers
6472 provided as the userData argument; the first is the expected
6473 element name, and the second is the expected attribute name.
6474 */
6475 static int triplet_start_flag = XML_FALSE;
6476 static int triplet_end_flag = XML_FALSE;
6477
6478 static void XMLCALL
triplet_start_checker(void * userData,const XML_Char * name,const XML_Char ** atts)6479 triplet_start_checker(void *userData, const XML_Char *name,
6480 const XML_Char **atts) {
6481 XML_Char **elemstr = (XML_Char **)userData;
6482 char buffer[1024];
6483 if (xcstrcmp(elemstr[0], name) != 0) {
6484 sprintf(buffer, "unexpected start string: '%" XML_FMT_STR "'", name);
6485 fail(buffer);
6486 }
6487 if (xcstrcmp(elemstr[1], atts[0]) != 0) {
6488 sprintf(buffer, "unexpected attribute string: '%" XML_FMT_STR "'", atts[0]);
6489 fail(buffer);
6490 }
6491 triplet_start_flag = XML_TRUE;
6492 }
6493
6494 /* Check that the element name passed to the end-element handler matches
6495 the expected value. The expected value is passed as the first element
6496 in an array of strings passed as the userData argument.
6497 */
6498 static void XMLCALL
triplet_end_checker(void * userData,const XML_Char * name)6499 triplet_end_checker(void *userData, const XML_Char *name) {
6500 XML_Char **elemstr = (XML_Char **)userData;
6501 if (xcstrcmp(elemstr[0], name) != 0) {
6502 char buffer[1024];
6503 sprintf(buffer, "unexpected end string: '%" XML_FMT_STR "'", name);
6504 fail(buffer);
6505 }
6506 triplet_end_flag = XML_TRUE;
6507 }
6508
START_TEST(test_return_ns_triplet)6509 START_TEST(test_return_ns_triplet) {
6510 const char *text = "<foo:e xmlns:foo='http://example.org/' bar:a='12'\n"
6511 " xmlns:bar='http://example.org/'>";
6512 const char *epilog = "</foo:e>";
6513 const XML_Char *elemstr[]
6514 = {XCS("http://example.org/ e foo"), XCS("http://example.org/ a bar")};
6515 XML_SetReturnNSTriplet(g_parser, XML_TRUE);
6516 XML_SetUserData(g_parser, (void *)elemstr);
6517 XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
6518 XML_SetNamespaceDeclHandler(g_parser, dummy_start_namespace_decl_handler,
6519 dummy_end_namespace_decl_handler);
6520 triplet_start_flag = XML_FALSE;
6521 triplet_end_flag = XML_FALSE;
6522 dummy_handler_flags = 0;
6523 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
6524 == XML_STATUS_ERROR)
6525 xml_failure(g_parser);
6526 if (! triplet_start_flag)
6527 fail("triplet_start_checker not invoked");
6528 /* Check that unsetting "return triplets" fails while still parsing */
6529 XML_SetReturnNSTriplet(g_parser, XML_FALSE);
6530 if (_XML_Parse_SINGLE_BYTES(g_parser, epilog, (int)strlen(epilog), XML_TRUE)
6531 == XML_STATUS_ERROR)
6532 xml_failure(g_parser);
6533 if (! triplet_end_flag)
6534 fail("triplet_end_checker not invoked");
6535 if (dummy_handler_flags
6536 != (DUMMY_START_NS_DECL_HANDLER_FLAG | DUMMY_END_NS_DECL_HANDLER_FLAG))
6537 fail("Namespace handlers not called");
6538 }
6539 END_TEST
6540
6541 static void XMLCALL
overwrite_start_checker(void * userData,const XML_Char * name,const XML_Char ** atts)6542 overwrite_start_checker(void *userData, const XML_Char *name,
6543 const XML_Char **atts) {
6544 CharData *storage = (CharData *)userData;
6545 CharData_AppendXMLChars(storage, XCS("start "), 6);
6546 CharData_AppendXMLChars(storage, name, -1);
6547 while (*atts != NULL) {
6548 CharData_AppendXMLChars(storage, XCS("\nattribute "), 11);
6549 CharData_AppendXMLChars(storage, *atts, -1);
6550 atts += 2;
6551 }
6552 CharData_AppendXMLChars(storage, XCS("\n"), 1);
6553 }
6554
6555 static void XMLCALL
overwrite_end_checker(void * userData,const XML_Char * name)6556 overwrite_end_checker(void *userData, const XML_Char *name) {
6557 CharData *storage = (CharData *)userData;
6558 CharData_AppendXMLChars(storage, XCS("end "), 4);
6559 CharData_AppendXMLChars(storage, name, -1);
6560 CharData_AppendXMLChars(storage, XCS("\n"), 1);
6561 }
6562
6563 static void
run_ns_tagname_overwrite_test(const char * text,const XML_Char * result)6564 run_ns_tagname_overwrite_test(const char *text, const XML_Char *result) {
6565 CharData storage;
6566 CharData_Init(&storage);
6567 XML_SetUserData(g_parser, &storage);
6568 XML_SetElementHandler(g_parser, overwrite_start_checker,
6569 overwrite_end_checker);
6570 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6571 == XML_STATUS_ERROR)
6572 xml_failure(g_parser);
6573 CharData_CheckXMLChars(&storage, result);
6574 }
6575
6576 /* Regression test for SF bug #566334. */
START_TEST(test_ns_tagname_overwrite)6577 START_TEST(test_ns_tagname_overwrite) {
6578 const char *text = "<n:e xmlns:n='http://example.org/'>\n"
6579 " <n:f n:attr='foo'/>\n"
6580 " <n:g n:attr2='bar'/>\n"
6581 "</n:e>";
6582 const XML_Char *result = XCS("start http://example.org/ e\n")
6583 XCS("start http://example.org/ f\n")
6584 XCS("attribute http://example.org/ attr\n")
6585 XCS("end http://example.org/ f\n")
6586 XCS("start http://example.org/ g\n")
6587 XCS("attribute http://example.org/ attr2\n")
6588 XCS("end http://example.org/ g\n")
6589 XCS("end http://example.org/ e\n");
6590 run_ns_tagname_overwrite_test(text, result);
6591 }
6592 END_TEST
6593
6594 /* Regression test for SF bug #566334. */
START_TEST(test_ns_tagname_overwrite_triplet)6595 START_TEST(test_ns_tagname_overwrite_triplet) {
6596 const char *text = "<n:e xmlns:n='http://example.org/'>\n"
6597 " <n:f n:attr='foo'/>\n"
6598 " <n:g n:attr2='bar'/>\n"
6599 "</n:e>";
6600 const XML_Char *result = XCS("start http://example.org/ e n\n")
6601 XCS("start http://example.org/ f n\n")
6602 XCS("attribute http://example.org/ attr n\n")
6603 XCS("end http://example.org/ f n\n")
6604 XCS("start http://example.org/ g n\n")
6605 XCS("attribute http://example.org/ attr2 n\n")
6606 XCS("end http://example.org/ g n\n")
6607 XCS("end http://example.org/ e n\n");
6608 XML_SetReturnNSTriplet(g_parser, XML_TRUE);
6609 run_ns_tagname_overwrite_test(text, result);
6610 }
6611 END_TEST
6612
6613 /* Regression test for SF bug #620343. */
6614 static void XMLCALL
start_element_fail(void * userData,const XML_Char * name,const XML_Char ** atts)6615 start_element_fail(void *userData, const XML_Char *name,
6616 const XML_Char **atts) {
6617 UNUSED_P(userData);
6618 UNUSED_P(name);
6619 UNUSED_P(atts);
6620
6621 /* We should never get here. */
6622 fail("should never reach start_element_fail()");
6623 }
6624
6625 static void XMLCALL
start_ns_clearing_start_element(void * userData,const XML_Char * prefix,const XML_Char * uri)6626 start_ns_clearing_start_element(void *userData, const XML_Char *prefix,
6627 const XML_Char *uri) {
6628 UNUSED_P(prefix);
6629 UNUSED_P(uri);
6630 XML_SetStartElementHandler((XML_Parser)userData, NULL);
6631 }
6632
START_TEST(test_start_ns_clears_start_element)6633 START_TEST(test_start_ns_clears_start_element) {
6634 /* This needs to use separate start/end tags; using the empty tag
6635 syntax doesn't cause the problematic path through Expat to be
6636 taken.
6637 */
6638 const char *text = "<e xmlns='http://example.org/'></e>";
6639
6640 XML_SetStartElementHandler(g_parser, start_element_fail);
6641 XML_SetStartNamespaceDeclHandler(g_parser, start_ns_clearing_start_element);
6642 XML_SetEndNamespaceDeclHandler(g_parser, dummy_end_namespace_decl_handler);
6643 XML_UseParserAsHandlerArg(g_parser);
6644 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6645 == XML_STATUS_ERROR)
6646 xml_failure(g_parser);
6647 }
6648 END_TEST
6649
6650 /* Regression test for SF bug #616863. */
6651 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)6652 external_entity_handler(XML_Parser parser, const XML_Char *context,
6653 const XML_Char *base, const XML_Char *systemId,
6654 const XML_Char *publicId) {
6655 intptr_t callno = 1 + (intptr_t)XML_GetUserData(parser);
6656 const char *text;
6657 XML_Parser p2;
6658
6659 UNUSED_P(base);
6660 UNUSED_P(systemId);
6661 UNUSED_P(publicId);
6662 if (callno == 1)
6663 text = ("<!ELEMENT doc (e+)>\n"
6664 "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
6665 "<!ELEMENT e EMPTY>\n");
6666 else
6667 text = ("<?xml version='1.0' encoding='us-ascii'?>"
6668 "<e/>");
6669
6670 XML_SetUserData(parser, (void *)callno);
6671 p2 = XML_ExternalEntityParserCreate(parser, context, NULL);
6672 if (_XML_Parse_SINGLE_BYTES(p2, text, (int)strlen(text), XML_TRUE)
6673 == XML_STATUS_ERROR) {
6674 xml_failure(p2);
6675 return XML_STATUS_ERROR;
6676 }
6677 XML_ParserFree(p2);
6678 return XML_STATUS_OK;
6679 }
6680
START_TEST(test_default_ns_from_ext_subset_and_ext_ge)6681 START_TEST(test_default_ns_from_ext_subset_and_ext_ge) {
6682 const char *text = "<?xml version='1.0'?>\n"
6683 "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n"
6684 " <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n"
6685 "]>\n"
6686 "<doc xmlns='http://example.org/ns1'>\n"
6687 "&en;\n"
6688 "</doc>";
6689
6690 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6691 XML_SetExternalEntityRefHandler(g_parser, external_entity_handler);
6692 /* We actually need to set this handler to tickle this bug. */
6693 XML_SetStartElementHandler(g_parser, dummy_start_element);
6694 XML_SetUserData(g_parser, NULL);
6695 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6696 == XML_STATUS_ERROR)
6697 xml_failure(g_parser);
6698 }
6699 END_TEST
6700
6701 /* Regression test #1 for SF bug #673791. */
START_TEST(test_ns_prefix_with_empty_uri_1)6702 START_TEST(test_ns_prefix_with_empty_uri_1) {
6703 const char *text = "<doc xmlns:prefix='http://example.org/'>\n"
6704 " <e xmlns:prefix=''/>\n"
6705 "</doc>";
6706
6707 expect_failure(text, XML_ERROR_UNDECLARING_PREFIX,
6708 "Did not report re-setting namespace"
6709 " URI with prefix to ''.");
6710 }
6711 END_TEST
6712
6713 /* Regression test #2 for SF bug #673791. */
START_TEST(test_ns_prefix_with_empty_uri_2)6714 START_TEST(test_ns_prefix_with_empty_uri_2) {
6715 const char *text = "<?xml version='1.0'?>\n"
6716 "<docelem xmlns:pre=''/>";
6717
6718 expect_failure(text, XML_ERROR_UNDECLARING_PREFIX,
6719 "Did not report setting namespace URI with prefix to ''.");
6720 }
6721 END_TEST
6722
6723 /* Regression test #3 for SF bug #673791. */
START_TEST(test_ns_prefix_with_empty_uri_3)6724 START_TEST(test_ns_prefix_with_empty_uri_3) {
6725 const char *text = "<!DOCTYPE doc [\n"
6726 " <!ELEMENT doc EMPTY>\n"
6727 " <!ATTLIST doc\n"
6728 " xmlns:prefix CDATA ''>\n"
6729 "]>\n"
6730 "<doc/>";
6731
6732 expect_failure(text, XML_ERROR_UNDECLARING_PREFIX,
6733 "Didn't report attr default setting NS w/ prefix to ''.");
6734 }
6735 END_TEST
6736
6737 /* Regression test #4 for SF bug #673791. */
START_TEST(test_ns_prefix_with_empty_uri_4)6738 START_TEST(test_ns_prefix_with_empty_uri_4) {
6739 const char *text = "<!DOCTYPE doc [\n"
6740 " <!ELEMENT prefix:doc EMPTY>\n"
6741 " <!ATTLIST prefix:doc\n"
6742 " xmlns:prefix CDATA 'http://example.org/'>\n"
6743 "]>\n"
6744 "<prefix:doc/>";
6745 /* Packaged info expected by the end element handler;
6746 the weird structuring lets us re-use the triplet_end_checker()
6747 function also used for another test. */
6748 const XML_Char *elemstr[] = {XCS("http://example.org/ doc prefix")};
6749 XML_SetReturnNSTriplet(g_parser, XML_TRUE);
6750 XML_SetUserData(g_parser, (void *)elemstr);
6751 XML_SetEndElementHandler(g_parser, triplet_end_checker);
6752 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6753 == XML_STATUS_ERROR)
6754 xml_failure(g_parser);
6755 }
6756 END_TEST
6757
6758 /* Test with non-xmlns prefix */
START_TEST(test_ns_unbound_prefix)6759 START_TEST(test_ns_unbound_prefix) {
6760 const char *text = "<!DOCTYPE doc [\n"
6761 " <!ELEMENT prefix:doc EMPTY>\n"
6762 " <!ATTLIST prefix:doc\n"
6763 " notxmlns:prefix CDATA 'http://example.org/'>\n"
6764 "]>\n"
6765 "<prefix:doc/>";
6766
6767 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6768 != XML_STATUS_ERROR)
6769 fail("Unbound prefix incorrectly passed");
6770 if (XML_GetErrorCode(g_parser) != XML_ERROR_UNBOUND_PREFIX)
6771 xml_failure(g_parser);
6772 }
6773 END_TEST
6774
START_TEST(test_ns_default_with_empty_uri)6775 START_TEST(test_ns_default_with_empty_uri) {
6776 const char *text = "<doc xmlns='http://example.org/'>\n"
6777 " <e xmlns=''/>\n"
6778 "</doc>";
6779 /* Add some handlers to exercise extra code paths */
6780 XML_SetStartNamespaceDeclHandler(g_parser,
6781 dummy_start_namespace_decl_handler);
6782 XML_SetEndNamespaceDeclHandler(g_parser, dummy_end_namespace_decl_handler);
6783 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6784 == XML_STATUS_ERROR)
6785 xml_failure(g_parser);
6786 }
6787 END_TEST
6788
6789 /* Regression test for SF bug #692964: two prefixes for one namespace. */
START_TEST(test_ns_duplicate_attrs_diff_prefixes)6790 START_TEST(test_ns_duplicate_attrs_diff_prefixes) {
6791 const char *text = "<doc xmlns:a='http://example.org/a'\n"
6792 " xmlns:b='http://example.org/a'\n"
6793 " a:a='v' b:a='v' />";
6794 expect_failure(text, XML_ERROR_DUPLICATE_ATTRIBUTE,
6795 "did not report multiple attributes with same URI+name");
6796 }
6797 END_TEST
6798
START_TEST(test_ns_duplicate_hashes)6799 START_TEST(test_ns_duplicate_hashes) {
6800 /* The hash of an attribute is calculated as the hash of its URI
6801 * concatenated with a space followed by its name (after the
6802 * colon). We wish to generate attributes with the same hash
6803 * value modulo the attribute table size so that we can check that
6804 * the attribute hash table works correctly. The attribute hash
6805 * table size will be the smallest power of two greater than the
6806 * number of attributes, but at least eight. There is
6807 * unfortunately no programmatic way of getting the hash or the
6808 * table size at user level, but the test code coverage percentage
6809 * will drop if the hashes cease to point to the same row.
6810 *
6811 * The cunning plan is to have few enough attributes to have a
6812 * reliable table size of 8, and have the single letter attribute
6813 * names be 8 characters apart, producing a hash which will be the
6814 * same modulo 8.
6815 */
6816 const char *text = "<doc xmlns:a='http://example.org/a'\n"
6817 " a:a='v' a:i='w' />";
6818 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6819 == XML_STATUS_ERROR)
6820 xml_failure(g_parser);
6821 }
6822 END_TEST
6823
6824 /* Regression test for SF bug #695401: unbound prefix. */
START_TEST(test_ns_unbound_prefix_on_attribute)6825 START_TEST(test_ns_unbound_prefix_on_attribute) {
6826 const char *text = "<doc a:attr=''/>";
6827 expect_failure(text, XML_ERROR_UNBOUND_PREFIX,
6828 "did not report unbound prefix on attribute");
6829 }
6830 END_TEST
6831
6832 /* Regression test for SF bug #695401: unbound prefix. */
START_TEST(test_ns_unbound_prefix_on_element)6833 START_TEST(test_ns_unbound_prefix_on_element) {
6834 const char *text = "<a:doc/>";
6835 expect_failure(text, XML_ERROR_UNBOUND_PREFIX,
6836 "did not report unbound prefix on element");
6837 }
6838 END_TEST
6839
6840 /* Test that the parsing status is correctly reset by XML_ParserReset().
6841 * We usE test_return_ns_triplet() for our example parse to improve
6842 * coverage of tidying up code executed.
6843 */
START_TEST(test_ns_parser_reset)6844 START_TEST(test_ns_parser_reset) {
6845 XML_ParsingStatus status;
6846
6847 XML_GetParsingStatus(g_parser, &status);
6848 if (status.parsing != XML_INITIALIZED)
6849 fail("parsing status doesn't start INITIALIZED");
6850 test_return_ns_triplet();
6851 XML_GetParsingStatus(g_parser, &status);
6852 if (status.parsing != XML_FINISHED)
6853 fail("parsing status doesn't end FINISHED");
6854 XML_ParserReset(g_parser, NULL);
6855 XML_GetParsingStatus(g_parser, &status);
6856 if (status.parsing != XML_INITIALIZED)
6857 fail("parsing status doesn't reset to INITIALIZED");
6858 }
6859 END_TEST
6860
6861 /* Test that long element names with namespaces are handled correctly */
START_TEST(test_ns_long_element)6862 START_TEST(test_ns_long_element) {
6863 const char *text
6864 = "<foo:thisisalongenoughelementnametotriggerareallocation\n"
6865 " xmlns:foo='http://example.org/' bar:a='12'\n"
6866 " xmlns:bar='http://example.org/'>"
6867 "</foo:thisisalongenoughelementnametotriggerareallocation>";
6868 const XML_Char *elemstr[]
6869 = {XCS("http://example.org/")
6870 XCS(" thisisalongenoughelementnametotriggerareallocation foo"),
6871 XCS("http://example.org/ a bar")};
6872
6873 XML_SetReturnNSTriplet(g_parser, XML_TRUE);
6874 XML_SetUserData(g_parser, (void *)elemstr);
6875 XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
6876 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6877 == XML_STATUS_ERROR)
6878 xml_failure(g_parser);
6879 }
6880 END_TEST
6881
6882 /* Test mixed population of prefixed and unprefixed attributes */
START_TEST(test_ns_mixed_prefix_atts)6883 START_TEST(test_ns_mixed_prefix_atts) {
6884 const char *text = "<e a='12' bar:b='13'\n"
6885 " xmlns:bar='http://example.org/'>"
6886 "</e>";
6887
6888 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6889 == XML_STATUS_ERROR)
6890 xml_failure(g_parser);
6891 }
6892 END_TEST
6893
6894 /* Test having a long namespaced element name inside a short one.
6895 * This exercises some internal buffer reallocation that is shared
6896 * across elements with the same namespace URI.
6897 */
START_TEST(test_ns_extend_uri_buffer)6898 START_TEST(test_ns_extend_uri_buffer) {
6899 const char *text = "<foo:e xmlns:foo='http://example.org/'>"
6900 " <foo:thisisalongenoughnametotriggerallocationaction"
6901 " foo:a='12' />"
6902 "</foo:e>";
6903 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6904 == XML_STATUS_ERROR)
6905 xml_failure(g_parser);
6906 }
6907 END_TEST
6908
6909 /* Test that xmlns is correctly rejected as an attribute in the xmlns
6910 * namespace, but not in other namespaces
6911 */
START_TEST(test_ns_reserved_attributes)6912 START_TEST(test_ns_reserved_attributes) {
6913 const char *text1
6914 = "<foo:e xmlns:foo='http://example.org/' xmlns:xmlns='12' />";
6915 const char *text2
6916 = "<foo:e xmlns:foo='http://example.org/' foo:xmlns='12' />";
6917 expect_failure(text1, XML_ERROR_RESERVED_PREFIX_XMLNS,
6918 "xmlns not rejected as an attribute");
6919 XML_ParserReset(g_parser, NULL);
6920 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
6921 == XML_STATUS_ERROR)
6922 xml_failure(g_parser);
6923 }
6924 END_TEST
6925
6926 /* Test more reserved attributes */
START_TEST(test_ns_reserved_attributes_2)6927 START_TEST(test_ns_reserved_attributes_2) {
6928 const char *text1 = "<foo:e xmlns:foo='http://example.org/'"
6929 " xmlns:xml='http://example.org/' />";
6930 const char *text2
6931 = "<foo:e xmlns:foo='http://www.w3.org/XML/1998/namespace' />";
6932 const char *text3 = "<foo:e xmlns:foo='http://www.w3.org/2000/xmlns/' />";
6933
6934 expect_failure(text1, XML_ERROR_RESERVED_PREFIX_XML,
6935 "xml not rejected as an attribute");
6936 XML_ParserReset(g_parser, NULL);
6937 expect_failure(text2, XML_ERROR_RESERVED_NAMESPACE_URI,
6938 "Use of w3.org URL not faulted");
6939 XML_ParserReset(g_parser, NULL);
6940 expect_failure(text3, XML_ERROR_RESERVED_NAMESPACE_URI,
6941 "Use of w3.org xmlns URL not faulted");
6942 }
6943 END_TEST
6944
6945 /* Test string pool handling of namespace names of 2048 characters */
6946 /* Exercises a particular string pool growth path */
START_TEST(test_ns_extremely_long_prefix)6947 START_TEST(test_ns_extremely_long_prefix) {
6948 /* C99 compilers are only required to support 4095-character
6949 * strings, so the following needs to be split in two to be safe
6950 * for all compilers.
6951 */
6952 const char *text1
6953 = "<doc "
6954 /* 64 character on each line */
6955 /* ...gives a total length of 2048 */
6956 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6957 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6958 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6959 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
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 ":a='12'";
6989 const char *text2
6990 = " xmlns:"
6991 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6992 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6993 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6994 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
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 "='foo'\n>"
7024 "</doc>";
7025
7026 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
7027 == XML_STATUS_ERROR)
7028 xml_failure(g_parser);
7029 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
7030 == XML_STATUS_ERROR)
7031 xml_failure(g_parser);
7032 }
7033 END_TEST
7034
7035 /* Test unknown encoding handlers in namespace setup */
START_TEST(test_ns_unknown_encoding_success)7036 START_TEST(test_ns_unknown_encoding_success) {
7037 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
7038 "<foo:e xmlns:foo='http://example.org/'>Hi</foo:e>";
7039
7040 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
7041 run_character_check(text, XCS("Hi"));
7042 }
7043 END_TEST
7044
7045 /* Test that too many colons are rejected */
START_TEST(test_ns_double_colon)7046 START_TEST(test_ns_double_colon) {
7047 const char *text = "<foo:e xmlns:foo='http://example.org/' foo:a:b='bar' />";
7048 const enum XML_Status status
7049 = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE);
7050 #ifdef XML_NS
7051 if ((status == XML_STATUS_OK)
7052 || (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)) {
7053 fail("Double colon in attribute name not faulted"
7054 " (despite active namespace support)");
7055 }
7056 #else
7057 if (status != XML_STATUS_OK) {
7058 fail("Double colon in attribute name faulted"
7059 " (despite inactive namespace support");
7060 }
7061 #endif
7062 }
7063 END_TEST
7064
START_TEST(test_ns_double_colon_element)7065 START_TEST(test_ns_double_colon_element) {
7066 const char *text = "<foo:bar:e xmlns:foo='http://example.org/' />";
7067 const enum XML_Status status
7068 = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE);
7069 #ifdef XML_NS
7070 if ((status == XML_STATUS_OK)
7071 || (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)) {
7072 fail("Double colon in element name not faulted"
7073 " (despite active namespace support)");
7074 }
7075 #else
7076 if (status != XML_STATUS_OK) {
7077 fail("Double colon in element name faulted"
7078 " (despite inactive namespace support");
7079 }
7080 #endif
7081 }
7082 END_TEST
7083
7084 /* Test that non-name characters after a colon are rejected */
START_TEST(test_ns_bad_attr_leafname)7085 START_TEST(test_ns_bad_attr_leafname) {
7086 const char *text = "<foo:e xmlns:foo='http://example.org/' foo:?ar='baz' />";
7087
7088 expect_failure(text, XML_ERROR_INVALID_TOKEN,
7089 "Invalid character in leafname not faulted");
7090 }
7091 END_TEST
7092
START_TEST(test_ns_bad_element_leafname)7093 START_TEST(test_ns_bad_element_leafname) {
7094 const char *text = "<foo:?oc xmlns:foo='http://example.org/' />";
7095
7096 expect_failure(text, XML_ERROR_INVALID_TOKEN,
7097 "Invalid character in element leafname not faulted");
7098 }
7099 END_TEST
7100
7101 /* Test high-byte-set UTF-16 characters are valid in a leafname */
START_TEST(test_ns_utf16_leafname)7102 START_TEST(test_ns_utf16_leafname) {
7103 const char text[] =
7104 /* <n:e xmlns:n='URI' n:{KHO KHWAI}='a' />
7105 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
7106 */
7107 "<\0n\0:\0e\0 \0x\0m\0l\0n\0s\0:\0n\0=\0'\0U\0R\0I\0'\0 \0"
7108 "n\0:\0\x04\x0e=\0'\0a\0'\0 \0/\0>\0";
7109 const XML_Char *expected = XCS("a");
7110 CharData storage;
7111
7112 CharData_Init(&storage);
7113 XML_SetStartElementHandler(g_parser, accumulate_attribute);
7114 XML_SetUserData(g_parser, &storage);
7115 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
7116 == XML_STATUS_ERROR)
7117 xml_failure(g_parser);
7118 CharData_CheckXMLChars(&storage, expected);
7119 }
7120 END_TEST
7121
START_TEST(test_ns_utf16_element_leafname)7122 START_TEST(test_ns_utf16_element_leafname) {
7123 const char text[] =
7124 /* <n:{KHO KHWAI} xmlns:n='URI'/>
7125 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
7126 */
7127 "\0<\0n\0:\x0e\x04\0 \0x\0m\0l\0n\0s\0:\0n\0=\0'\0U\0R\0I\0'\0/\0>";
7128 #ifdef XML_UNICODE
7129 const XML_Char *expected = XCS("URI \x0e04");
7130 #else
7131 const XML_Char *expected = XCS("URI \xe0\xb8\x84");
7132 #endif
7133 CharData storage;
7134
7135 CharData_Init(&storage);
7136 XML_SetStartElementHandler(g_parser, start_element_event_handler);
7137 XML_SetUserData(g_parser, &storage);
7138 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
7139 == XML_STATUS_ERROR)
7140 xml_failure(g_parser);
7141 CharData_CheckXMLChars(&storage, expected);
7142 }
7143 END_TEST
7144
START_TEST(test_ns_utf16_doctype)7145 START_TEST(test_ns_utf16_doctype) {
7146 const char text[] =
7147 /* <!DOCTYPE foo:{KHO KHWAI} [ <!ENTITY bar 'baz'> ]>\n
7148 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
7149 */
7150 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0f\0o\0o\0:\x0e\x04\0 "
7151 "\0[\0 \0<\0!\0E\0N\0T\0I\0T\0Y\0 \0b\0a\0r\0 \0'\0b\0a\0z\0'\0>\0 "
7152 "\0]\0>\0\n"
7153 /* <foo:{KHO KHWAI} xmlns:foo='URI'>&bar;</foo:{KHO KHWAI}> */
7154 "\0<\0f\0o\0o\0:\x0e\x04\0 "
7155 "\0x\0m\0l\0n\0s\0:\0f\0o\0o\0=\0'\0U\0R\0I\0'\0>"
7156 "\0&\0b\0a\0r\0;"
7157 "\0<\0/\0f\0o\0o\0:\x0e\x04\0>";
7158 #ifdef XML_UNICODE
7159 const XML_Char *expected = XCS("URI \x0e04");
7160 #else
7161 const XML_Char *expected = XCS("URI \xe0\xb8\x84");
7162 #endif
7163 CharData storage;
7164
7165 CharData_Init(&storage);
7166 XML_SetUserData(g_parser, &storage);
7167 XML_SetStartElementHandler(g_parser, start_element_event_handler);
7168 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
7169 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
7170 == XML_STATUS_ERROR)
7171 xml_failure(g_parser);
7172 CharData_CheckXMLChars(&storage, expected);
7173 }
7174 END_TEST
7175
START_TEST(test_ns_invalid_doctype)7176 START_TEST(test_ns_invalid_doctype) {
7177 const char *text = "<!DOCTYPE foo:!bad [ <!ENTITY bar 'baz' ]>\n"
7178 "<foo:!bad>&bar;</foo:!bad>";
7179
7180 expect_failure(text, XML_ERROR_INVALID_TOKEN,
7181 "Invalid character in document local name not faulted");
7182 }
7183 END_TEST
7184
START_TEST(test_ns_double_colon_doctype)7185 START_TEST(test_ns_double_colon_doctype) {
7186 const char *text = "<!DOCTYPE foo:a:doc [ <!ENTITY bar 'baz' ]>\n"
7187 "<foo:a:doc>&bar;</foo:a:doc>";
7188
7189 expect_failure(text, XML_ERROR_SYNTAX,
7190 "Double colon in document name not faulted");
7191 }
7192 END_TEST
7193
7194 /* Control variable; the number of times duff_allocator() will successfully
7195 * allocate */
7196 #define ALLOC_ALWAYS_SUCCEED (-1)
7197 #define REALLOC_ALWAYS_SUCCEED (-1)
7198
7199 static intptr_t allocation_count = ALLOC_ALWAYS_SUCCEED;
7200 static intptr_t reallocation_count = REALLOC_ALWAYS_SUCCEED;
7201
7202 /* Crocked allocator for allocation failure tests */
7203 static void *
duff_allocator(size_t size)7204 duff_allocator(size_t size) {
7205 if (allocation_count == 0)
7206 return NULL;
7207 if (allocation_count != ALLOC_ALWAYS_SUCCEED)
7208 allocation_count--;
7209 return malloc(size);
7210 }
7211
7212 /* Crocked reallocator for allocation failure tests */
7213 static void *
duff_reallocator(void * ptr,size_t size)7214 duff_reallocator(void *ptr, size_t size) {
7215 if (reallocation_count == 0)
7216 return NULL;
7217 if (reallocation_count != REALLOC_ALWAYS_SUCCEED)
7218 reallocation_count--;
7219 return realloc(ptr, size);
7220 }
7221
7222 /* Test that a failure to allocate the parser structure fails gracefully */
START_TEST(test_misc_alloc_create_parser)7223 START_TEST(test_misc_alloc_create_parser) {
7224 XML_Memory_Handling_Suite memsuite = {duff_allocator, realloc, free};
7225 unsigned int i;
7226 const unsigned int max_alloc_count = 10;
7227
7228 /* Something this simple shouldn't need more than 10 allocations */
7229 for (i = 0; i < max_alloc_count; i++) {
7230 allocation_count = i;
7231 g_parser = XML_ParserCreate_MM(NULL, &memsuite, NULL);
7232 if (g_parser != NULL)
7233 break;
7234 }
7235 if (i == 0)
7236 fail("Parser unexpectedly ignored failing allocator");
7237 else if (i == max_alloc_count)
7238 fail("Parser not created with max allocation count");
7239 }
7240 END_TEST
7241
7242 /* Test memory allocation failures for a parser with an encoding */
START_TEST(test_misc_alloc_create_parser_with_encoding)7243 START_TEST(test_misc_alloc_create_parser_with_encoding) {
7244 XML_Memory_Handling_Suite memsuite = {duff_allocator, realloc, free};
7245 unsigned int i;
7246 const unsigned int max_alloc_count = 10;
7247
7248 /* Try several levels of allocation */
7249 for (i = 0; i < max_alloc_count; i++) {
7250 allocation_count = i;
7251 g_parser = XML_ParserCreate_MM(XCS("us-ascii"), &memsuite, NULL);
7252 if (g_parser != NULL)
7253 break;
7254 }
7255 if (i == 0)
7256 fail("Parser ignored failing allocator");
7257 else if (i == max_alloc_count)
7258 fail("Parser not created with max allocation count");
7259 }
7260 END_TEST
7261
7262 /* Test that freeing a NULL parser doesn't cause an explosion.
7263 * (Not actually tested anywhere else)
7264 */
START_TEST(test_misc_null_parser)7265 START_TEST(test_misc_null_parser) {
7266 XML_ParserFree(NULL);
7267 }
7268 END_TEST
7269
7270 /* Test that XML_ErrorString rejects out-of-range codes */
START_TEST(test_misc_error_string)7271 START_TEST(test_misc_error_string) {
7272 if (XML_ErrorString((enum XML_Error) - 1) != NULL)
7273 fail("Negative error code not rejected");
7274 if (XML_ErrorString((enum XML_Error)100) != NULL)
7275 fail("Large error code not rejected");
7276 }
7277 END_TEST
7278
7279 /* Test the version information is consistent */
7280
7281 /* Since we are working in XML_LChars (potentially 16-bits), we
7282 * can't use the standard C library functions for character
7283 * manipulation and have to roll our own.
7284 */
7285 static int
parse_version(const XML_LChar * version_text,XML_Expat_Version * version_struct)7286 parse_version(const XML_LChar *version_text,
7287 XML_Expat_Version *version_struct) {
7288 if (! version_text)
7289 return XML_FALSE;
7290
7291 while (*version_text != 0x00) {
7292 if (*version_text >= ASCII_0 && *version_text <= ASCII_9)
7293 break;
7294 version_text++;
7295 }
7296 if (*version_text == 0x00)
7297 return XML_FALSE;
7298
7299 /* version_struct->major = strtoul(version_text, 10, &version_text) */
7300 version_struct->major = 0;
7301 while (*version_text >= ASCII_0 && *version_text <= ASCII_9) {
7302 version_struct->major
7303 = 10 * version_struct->major + (*version_text++ - ASCII_0);
7304 }
7305 if (*version_text++ != ASCII_PERIOD)
7306 return XML_FALSE;
7307
7308 /* Now for the minor version number */
7309 version_struct->minor = 0;
7310 while (*version_text >= ASCII_0 && *version_text <= ASCII_9) {
7311 version_struct->minor
7312 = 10 * version_struct->minor + (*version_text++ - ASCII_0);
7313 }
7314 if (*version_text++ != ASCII_PERIOD)
7315 return XML_FALSE;
7316
7317 /* Finally the micro version number */
7318 version_struct->micro = 0;
7319 while (*version_text >= ASCII_0 && *version_text <= ASCII_9) {
7320 version_struct->micro
7321 = 10 * version_struct->micro + (*version_text++ - ASCII_0);
7322 }
7323 if (*version_text != 0x00)
7324 return XML_FALSE;
7325 return XML_TRUE;
7326 }
7327
7328 static int
versions_equal(const XML_Expat_Version * first,const XML_Expat_Version * second)7329 versions_equal(const XML_Expat_Version *first,
7330 const XML_Expat_Version *second) {
7331 return (first->major == second->major && first->minor == second->minor
7332 && first->micro == second->micro);
7333 }
7334
START_TEST(test_misc_version)7335 START_TEST(test_misc_version) {
7336 XML_Expat_Version read_version = XML_ExpatVersionInfo();
7337 /* Silence compiler warning with the following assignment */
7338 XML_Expat_Version parsed_version = {0, 0, 0};
7339 const XML_LChar *version_text = XML_ExpatVersion();
7340
7341 if (version_text == NULL)
7342 fail("Could not obtain version text");
7343 assert(version_text != NULL);
7344 if (! parse_version(version_text, &parsed_version))
7345 fail("Unable to parse version text");
7346 if (! versions_equal(&read_version, &parsed_version))
7347 fail("Version mismatch");
7348
7349 #if ! defined(XML_UNICODE) || defined(XML_UNICODE_WCHAR_T)
7350 if (xcstrcmp(version_text, XCS("expat_2.3.0"))) /* needs bump on releases */
7351 fail("XML_*_VERSION in expat.h out of sync?\n");
7352 #else
7353 /* If we have XML_UNICODE defined but not XML_UNICODE_WCHAR_T
7354 * then XML_LChar is defined as char, for some reason.
7355 */
7356 if (strcmp(version_text, "expat_2.2.5")) /* needs bump on releases */
7357 fail("XML_*_VERSION in expat.h out of sync?\n");
7358 #endif /* ! defined(XML_UNICODE) || defined(XML_UNICODE_WCHAR_T) */
7359 }
7360 END_TEST
7361
7362 /* Test feature information */
START_TEST(test_misc_features)7363 START_TEST(test_misc_features) {
7364 const XML_Feature *features = XML_GetFeatureList();
7365
7366 /* Prevent problems with double-freeing parsers */
7367 g_parser = NULL;
7368 if (features == NULL) {
7369 fail("Failed to get feature information");
7370 } else {
7371 /* Loop through the features checking what we can */
7372 while (features->feature != XML_FEATURE_END) {
7373 switch (features->feature) {
7374 case XML_FEATURE_SIZEOF_XML_CHAR:
7375 if (features->value != sizeof(XML_Char))
7376 fail("Incorrect size of XML_Char");
7377 break;
7378 case XML_FEATURE_SIZEOF_XML_LCHAR:
7379 if (features->value != sizeof(XML_LChar))
7380 fail("Incorrect size of XML_LChar");
7381 break;
7382 default:
7383 break;
7384 }
7385 features++;
7386 }
7387 }
7388 }
7389 END_TEST
7390
7391 /* Regression test for GitHub Issue #17: memory leak parsing attribute
7392 * values with mixed bound and unbound namespaces.
7393 */
START_TEST(test_misc_attribute_leak)7394 START_TEST(test_misc_attribute_leak) {
7395 const char *text = "<D xmlns:L=\"D\" l:a='' L:a=''/>";
7396 XML_Memory_Handling_Suite memsuite
7397 = {tracking_malloc, tracking_realloc, tracking_free};
7398
7399 g_parser = XML_ParserCreate_MM(XCS("UTF-8"), &memsuite, XCS("\n"));
7400 expect_failure(text, XML_ERROR_UNBOUND_PREFIX, "Unbound prefixes not found");
7401 XML_ParserFree(g_parser);
7402 /* Prevent the teardown trying to double free */
7403 g_parser = NULL;
7404
7405 if (! tracking_report())
7406 fail("Memory leak found");
7407 }
7408 END_TEST
7409
7410 /* Test parser created for UTF-16LE is successful */
START_TEST(test_misc_utf16le)7411 START_TEST(test_misc_utf16le) {
7412 const char text[] =
7413 /* <?xml version='1.0'?><q>Hi</q> */
7414 "<\0?\0x\0m\0l\0 \0"
7415 "v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0?\0>\0"
7416 "<\0q\0>\0H\0i\0<\0/\0q\0>\0";
7417 const XML_Char *expected = XCS("Hi");
7418 CharData storage;
7419
7420 g_parser = XML_ParserCreate(XCS("UTF-16LE"));
7421 if (g_parser == NULL)
7422 fail("Parser not created");
7423
7424 CharData_Init(&storage);
7425 XML_SetUserData(g_parser, &storage);
7426 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
7427 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
7428 == XML_STATUS_ERROR)
7429 xml_failure(g_parser);
7430 CharData_CheckXMLChars(&storage, expected);
7431 }
7432 END_TEST
7433
7434 typedef struct {
7435 XML_Parser parser;
7436 int deep;
7437 } DataIssue240;
7438
7439 static void
start_element_issue_240(void * userData,const XML_Char * name,const XML_Char ** atts)7440 start_element_issue_240(void *userData, const XML_Char *name,
7441 const XML_Char **atts) {
7442 DataIssue240 *mydata = (DataIssue240 *)userData;
7443 UNUSED_P(name);
7444 UNUSED_P(atts);
7445 mydata->deep++;
7446 }
7447
7448 static void
end_element_issue_240(void * userData,const XML_Char * name)7449 end_element_issue_240(void *userData, const XML_Char *name) {
7450 DataIssue240 *mydata = (DataIssue240 *)userData;
7451
7452 UNUSED_P(name);
7453 mydata->deep--;
7454 if (mydata->deep == 0) {
7455 XML_StopParser(mydata->parser, 0);
7456 }
7457 }
7458
START_TEST(test_misc_stop_during_end_handler_issue_240_1)7459 START_TEST(test_misc_stop_during_end_handler_issue_240_1) {
7460 XML_Parser parser;
7461 DataIssue240 *mydata;
7462 enum XML_Status result;
7463 const char *const doc1 = "<doc><e1/><e><foo/></e></doc>";
7464
7465 parser = XML_ParserCreate(NULL);
7466 XML_SetElementHandler(parser, start_element_issue_240, end_element_issue_240);
7467 mydata = (DataIssue240 *)malloc(sizeof(DataIssue240));
7468 mydata->parser = parser;
7469 mydata->deep = 0;
7470 XML_SetUserData(parser, mydata);
7471
7472 result = XML_Parse(parser, doc1, (int)strlen(doc1), 1);
7473 XML_ParserFree(parser);
7474 free(mydata);
7475 if (result != XML_STATUS_ERROR)
7476 fail("Stopping the parser did not work as expected");
7477 }
7478 END_TEST
7479
START_TEST(test_misc_stop_during_end_handler_issue_240_2)7480 START_TEST(test_misc_stop_during_end_handler_issue_240_2) {
7481 XML_Parser parser;
7482 DataIssue240 *mydata;
7483 enum XML_Status result;
7484 const char *const doc2 = "<doc><elem/></doc>";
7485
7486 parser = XML_ParserCreate(NULL);
7487 XML_SetElementHandler(parser, start_element_issue_240, end_element_issue_240);
7488 mydata = (DataIssue240 *)malloc(sizeof(DataIssue240));
7489 mydata->parser = parser;
7490 mydata->deep = 0;
7491 XML_SetUserData(parser, mydata);
7492
7493 result = XML_Parse(parser, doc2, (int)strlen(doc2), 1);
7494 XML_ParserFree(parser);
7495 free(mydata);
7496 if (result != XML_STATUS_ERROR)
7497 fail("Stopping the parser did not work as expected");
7498 }
7499 END_TEST
7500
START_TEST(test_misc_deny_internal_entity_closing_doctype_issue_317)7501 START_TEST(test_misc_deny_internal_entity_closing_doctype_issue_317) {
7502 const char *const inputOne = "<!DOCTYPE d [\n"
7503 "<!ENTITY % e ']><d/>'>\n"
7504 "\n"
7505 "%e;";
7506 const char *const inputTwo = "<!DOCTYPE d [\n"
7507 "<!ENTITY % e1 ']><d/>'><!ENTITY % e2 '&e1;'>\n"
7508 "\n"
7509 "%e2;";
7510 const char *const inputThree = "<!DOCTYPE d [\n"
7511 "<!ENTITY % e ']><d'>\n"
7512 "\n"
7513 "%e;";
7514 const char *const inputIssue317 = "<!DOCTYPE doc [\n"
7515 "<!ENTITY % foo ']>\n"
7516 "<doc>Hell<oc (#PCDATA)*>'>\n"
7517 "%foo;\n"
7518 "]>\n"
7519 "<doc>Hello, world</dVc>";
7520
7521 const char *const inputs[] = {inputOne, inputTwo, inputThree, inputIssue317};
7522 size_t inputIndex = 0;
7523
7524 for (; inputIndex < sizeof(inputs) / sizeof(inputs[0]); inputIndex++) {
7525 XML_Parser parser;
7526 enum XML_Status parseResult;
7527 int setParamEntityResult;
7528 XML_Size lineNumber;
7529 XML_Size columnNumber;
7530 const char *const input = inputs[inputIndex];
7531
7532 parser = XML_ParserCreate(NULL);
7533 setParamEntityResult
7534 = XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
7535 if (setParamEntityResult != 1)
7536 fail("Failed to set XML_PARAM_ENTITY_PARSING_ALWAYS.");
7537
7538 parseResult = XML_Parse(parser, input, (int)strlen(input), 0);
7539 if (parseResult != XML_STATUS_ERROR) {
7540 parseResult = XML_Parse(parser, "", 0, 1);
7541 if (parseResult != XML_STATUS_ERROR) {
7542 fail("Parsing was expected to fail but succeeded.");
7543 }
7544 }
7545
7546 if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN)
7547 fail("Error code does not match XML_ERROR_INVALID_TOKEN");
7548
7549 lineNumber = XML_GetCurrentLineNumber(parser);
7550 if (lineNumber != 4)
7551 fail("XML_GetCurrentLineNumber does not work as expected.");
7552
7553 columnNumber = XML_GetCurrentColumnNumber(parser);
7554 if (columnNumber != 0)
7555 fail("XML_GetCurrentColumnNumber does not work as expected.");
7556
7557 XML_ParserFree(parser);
7558 }
7559 }
7560 END_TEST
7561
7562 static void
alloc_setup(void)7563 alloc_setup(void) {
7564 XML_Memory_Handling_Suite memsuite = {duff_allocator, duff_reallocator, free};
7565
7566 /* Ensure the parser creation will go through */
7567 allocation_count = ALLOC_ALWAYS_SUCCEED;
7568 reallocation_count = REALLOC_ALWAYS_SUCCEED;
7569 g_parser = XML_ParserCreate_MM(NULL, &memsuite, NULL);
7570 if (g_parser == NULL)
7571 fail("Parser not created");
7572 }
7573
7574 static void
alloc_teardown(void)7575 alloc_teardown(void) {
7576 basic_teardown();
7577 }
7578
7579 /* Test the effects of allocation failures on xml declaration processing */
START_TEST(test_alloc_parse_xdecl)7580 START_TEST(test_alloc_parse_xdecl) {
7581 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
7582 "<doc>Hello, world</doc>";
7583 int i;
7584 const int max_alloc_count = 15;
7585
7586 for (i = 0; i < max_alloc_count; i++) {
7587 allocation_count = i;
7588 XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler);
7589 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7590 != XML_STATUS_ERROR)
7591 break;
7592 /* Resetting the parser is insufficient, because some memory
7593 * allocations are cached within the parser. Instead we use
7594 * the teardown and setup routines to ensure that we have the
7595 * right sort of parser back in our hands.
7596 */
7597 alloc_teardown();
7598 alloc_setup();
7599 }
7600 if (i == 0)
7601 fail("Parse succeeded despite failing allocator");
7602 if (i == max_alloc_count)
7603 fail("Parse failed with max allocations");
7604 }
7605 END_TEST
7606
7607 /* As above, but with an encoding big enough to cause storing the
7608 * version information to expand the string pool being used.
7609 */
7610 static int XMLCALL
long_encoding_handler(void * userData,const XML_Char * encoding,XML_Encoding * info)7611 long_encoding_handler(void *userData, const XML_Char *encoding,
7612 XML_Encoding *info) {
7613 int i;
7614
7615 UNUSED_P(userData);
7616 UNUSED_P(encoding);
7617 for (i = 0; i < 256; i++)
7618 info->map[i] = i;
7619 info->data = NULL;
7620 info->convert = NULL;
7621 info->release = NULL;
7622 return XML_STATUS_OK;
7623 }
7624
START_TEST(test_alloc_parse_xdecl_2)7625 START_TEST(test_alloc_parse_xdecl_2) {
7626 const char *text
7627 = "<?xml version='1.0' encoding='"
7628 /* Each line is 64 characters */
7629 "ThisIsAStupidlyLongEncodingNameIntendedToTriggerPoolGrowth123456"
7630 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7631 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7632 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7633 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7634 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7635 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7636 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7637 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7638 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7639 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7640 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7641 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7642 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7643 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7644 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN"
7645 "'?>"
7646 "<doc>Hello, world</doc>";
7647 int i;
7648 const int max_alloc_count = 20;
7649
7650 for (i = 0; i < max_alloc_count; i++) {
7651 allocation_count = i;
7652 XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler);
7653 XML_SetUnknownEncodingHandler(g_parser, long_encoding_handler, NULL);
7654 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7655 != XML_STATUS_ERROR)
7656 break;
7657 /* See comment in test_alloc_parse_xdecl() */
7658 alloc_teardown();
7659 alloc_setup();
7660 }
7661 if (i == 0)
7662 fail("Parse succeeded despite failing allocator");
7663 if (i == max_alloc_count)
7664 fail("Parse failed with max allocations");
7665 }
7666 END_TEST
7667
7668 /* Test the effects of allocation failures on a straightforward parse */
START_TEST(test_alloc_parse_pi)7669 START_TEST(test_alloc_parse_pi) {
7670 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
7671 "<?pi unknown?>\n"
7672 "<doc>"
7673 "Hello, world"
7674 "</doc>";
7675 int i;
7676 const int max_alloc_count = 15;
7677
7678 for (i = 0; i < max_alloc_count; i++) {
7679 allocation_count = i;
7680 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
7681 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7682 != XML_STATUS_ERROR)
7683 break;
7684 /* See comment in test_alloc_parse_xdecl() */
7685 alloc_teardown();
7686 alloc_setup();
7687 }
7688 if (i == 0)
7689 fail("Parse succeeded despite failing allocator");
7690 if (i == max_alloc_count)
7691 fail("Parse failed with max allocations");
7692 }
7693 END_TEST
7694
START_TEST(test_alloc_parse_pi_2)7695 START_TEST(test_alloc_parse_pi_2) {
7696 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
7697 "<doc>"
7698 "Hello, world"
7699 "<?pi unknown?>\n"
7700 "</doc>";
7701 int i;
7702 const int max_alloc_count = 15;
7703
7704 for (i = 0; i < max_alloc_count; i++) {
7705 allocation_count = i;
7706 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
7707 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7708 != XML_STATUS_ERROR)
7709 break;
7710 /* See comment in test_alloc_parse_xdecl() */
7711 alloc_teardown();
7712 alloc_setup();
7713 }
7714 if (i == 0)
7715 fail("Parse succeeded despite failing allocator");
7716 if (i == max_alloc_count)
7717 fail("Parse failed with max allocations");
7718 }
7719 END_TEST
7720
START_TEST(test_alloc_parse_pi_3)7721 START_TEST(test_alloc_parse_pi_3) {
7722 const char *text
7723 = "<?"
7724 /* 64 characters per line */
7725 "This processing instruction should be long enough to ensure that"
7726 "it triggers the growth of an internal string pool when the "
7727 "allocator fails at a cruicial moment FGHIJKLMNOPABCDEFGHIJKLMNOP"
7728 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7729 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7730 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7731 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7732 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7733 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7734 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7735 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7736 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7737 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7738 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7739 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7740 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7741 "Q?><doc/>";
7742 int i;
7743 const int max_alloc_count = 20;
7744
7745 for (i = 0; i < max_alloc_count; i++) {
7746 allocation_count = i;
7747 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
7748 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7749 != XML_STATUS_ERROR)
7750 break;
7751 /* See comment in test_alloc_parse_xdecl() */
7752 alloc_teardown();
7753 alloc_setup();
7754 }
7755 if (i == 0)
7756 fail("Parse succeeded despite failing allocator");
7757 if (i == max_alloc_count)
7758 fail("Parse failed with max allocations");
7759 }
7760 END_TEST
7761
START_TEST(test_alloc_parse_comment)7762 START_TEST(test_alloc_parse_comment) {
7763 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
7764 "<!-- Test parsing this comment -->"
7765 "<doc>Hi</doc>";
7766 int i;
7767 const int max_alloc_count = 15;
7768
7769 for (i = 0; i < max_alloc_count; i++) {
7770 allocation_count = i;
7771 XML_SetCommentHandler(g_parser, dummy_comment_handler);
7772 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7773 != XML_STATUS_ERROR)
7774 break;
7775 /* See comment in test_alloc_parse_xdecl() */
7776 alloc_teardown();
7777 alloc_setup();
7778 }
7779 if (i == 0)
7780 fail("Parse succeeded despite failing allocator");
7781 if (i == max_alloc_count)
7782 fail("Parse failed with max allocations");
7783 }
7784 END_TEST
7785
START_TEST(test_alloc_parse_comment_2)7786 START_TEST(test_alloc_parse_comment_2) {
7787 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
7788 "<doc>"
7789 "Hello, world"
7790 "<!-- Parse this comment too -->"
7791 "</doc>";
7792 int i;
7793 const int max_alloc_count = 15;
7794
7795 for (i = 0; i < max_alloc_count; i++) {
7796 allocation_count = i;
7797 XML_SetCommentHandler(g_parser, dummy_comment_handler);
7798 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7799 != XML_STATUS_ERROR)
7800 break;
7801 /* See comment in test_alloc_parse_xdecl() */
7802 alloc_teardown();
7803 alloc_setup();
7804 }
7805 if (i == 0)
7806 fail("Parse succeeded despite failing allocator");
7807 if (i == max_alloc_count)
7808 fail("Parse failed with max allocations");
7809 }
7810 END_TEST
7811
7812 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)7813 external_entity_duff_loader(XML_Parser parser, const XML_Char *context,
7814 const XML_Char *base, const XML_Char *systemId,
7815 const XML_Char *publicId) {
7816 XML_Parser new_parser;
7817 unsigned int i;
7818 const unsigned int max_alloc_count = 10;
7819
7820 UNUSED_P(base);
7821 UNUSED_P(systemId);
7822 UNUSED_P(publicId);
7823 /* Try a few different allocation levels */
7824 for (i = 0; i < max_alloc_count; i++) {
7825 allocation_count = i;
7826 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
7827 if (new_parser != NULL) {
7828 XML_ParserFree(new_parser);
7829 break;
7830 }
7831 }
7832 if (i == 0)
7833 fail("External parser creation ignored failing allocator");
7834 else if (i == max_alloc_count)
7835 fail("Extern parser not created with max allocation count");
7836
7837 /* Make sure other random allocation doesn't now fail */
7838 allocation_count = ALLOC_ALWAYS_SUCCEED;
7839
7840 /* Make sure the failure code path is executed too */
7841 return XML_STATUS_ERROR;
7842 }
7843
7844 /* Test that external parser creation running out of memory is
7845 * correctly reported. Based on the external entity test cases.
7846 */
START_TEST(test_alloc_create_external_parser)7847 START_TEST(test_alloc_create_external_parser) {
7848 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
7849 "<!DOCTYPE doc SYSTEM 'foo'>\n"
7850 "<doc>&entity;</doc>";
7851 char foo_text[] = "<!ELEMENT doc (#PCDATA)*>";
7852
7853 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
7854 XML_SetUserData(g_parser, foo_text);
7855 XML_SetExternalEntityRefHandler(g_parser, external_entity_duff_loader);
7856 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7857 != XML_STATUS_ERROR) {
7858 fail("External parser allocator returned success incorrectly");
7859 }
7860 }
7861 END_TEST
7862
7863 /* More external parser memory allocation testing */
START_TEST(test_alloc_run_external_parser)7864 START_TEST(test_alloc_run_external_parser) {
7865 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
7866 "<!DOCTYPE doc SYSTEM 'foo'>\n"
7867 "<doc>&entity;</doc>";
7868 char foo_text[] = "<!ELEMENT doc (#PCDATA)*>";
7869 unsigned int i;
7870 const unsigned int max_alloc_count = 15;
7871
7872 for (i = 0; i < max_alloc_count; i++) {
7873 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
7874 XML_SetUserData(g_parser, foo_text);
7875 XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader);
7876 allocation_count = i;
7877 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7878 != XML_STATUS_ERROR)
7879 break;
7880 /* See comment in test_alloc_parse_xdecl() */
7881 alloc_teardown();
7882 alloc_setup();
7883 }
7884 if (i == 0)
7885 fail("Parsing ignored failing allocator");
7886 else if (i == max_alloc_count)
7887 fail("Parsing failed with allocation count 10");
7888 }
7889 END_TEST
7890
7891 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)7892 external_entity_dbl_handler(XML_Parser parser, const XML_Char *context,
7893 const XML_Char *base, const XML_Char *systemId,
7894 const XML_Char *publicId) {
7895 intptr_t callno = (intptr_t)XML_GetUserData(parser);
7896 const char *text;
7897 XML_Parser new_parser;
7898 int i;
7899 const int max_alloc_count = 20;
7900
7901 UNUSED_P(base);
7902 UNUSED_P(systemId);
7903 UNUSED_P(publicId);
7904 if (callno == 0) {
7905 /* First time through, check how many calls to malloc occur */
7906 text = ("<!ELEMENT doc (e+)>\n"
7907 "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
7908 "<!ELEMENT e EMPTY>\n");
7909 allocation_count = 10000;
7910 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
7911 if (new_parser == NULL) {
7912 fail("Unable to allocate first external parser");
7913 return XML_STATUS_ERROR;
7914 }
7915 /* Stash the number of calls in the user data */
7916 XML_SetUserData(parser, (void *)(intptr_t)(10000 - allocation_count));
7917 } else {
7918 text = ("<?xml version='1.0' encoding='us-ascii'?>"
7919 "<e/>");
7920 /* Try at varying levels to exercise more code paths */
7921 for (i = 0; i < max_alloc_count; i++) {
7922 allocation_count = callno + i;
7923 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
7924 if (new_parser != NULL)
7925 break;
7926 }
7927 if (i == 0) {
7928 fail("Second external parser unexpectedly created");
7929 XML_ParserFree(new_parser);
7930 return XML_STATUS_ERROR;
7931 } else if (i == max_alloc_count) {
7932 fail("Second external parser not created");
7933 return XML_STATUS_ERROR;
7934 }
7935 }
7936
7937 allocation_count = ALLOC_ALWAYS_SUCCEED;
7938 if (_XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE)
7939 == XML_STATUS_ERROR) {
7940 xml_failure(new_parser);
7941 return XML_STATUS_ERROR;
7942 }
7943 XML_ParserFree(new_parser);
7944 return XML_STATUS_OK;
7945 }
7946
7947 /* Test that running out of memory in dtdCopy is correctly reported.
7948 * Based on test_default_ns_from_ext_subset_and_ext_ge()
7949 */
START_TEST(test_alloc_dtd_copy_default_atts)7950 START_TEST(test_alloc_dtd_copy_default_atts) {
7951 const char *text = "<?xml version='1.0'?>\n"
7952 "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n"
7953 " <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n"
7954 "]>\n"
7955 "<doc xmlns='http://example.org/ns1'>\n"
7956 "&en;\n"
7957 "</doc>";
7958
7959 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
7960 XML_SetExternalEntityRefHandler(g_parser, external_entity_dbl_handler);
7961 XML_SetUserData(g_parser, NULL);
7962 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7963 == XML_STATUS_ERROR)
7964 xml_failure(g_parser);
7965 }
7966 END_TEST
7967
7968 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)7969 external_entity_dbl_handler_2(XML_Parser parser, const XML_Char *context,
7970 const XML_Char *base, const XML_Char *systemId,
7971 const XML_Char *publicId) {
7972 intptr_t callno = (intptr_t)XML_GetUserData(parser);
7973 const char *text;
7974 XML_Parser new_parser;
7975 enum XML_Status rv;
7976
7977 UNUSED_P(base);
7978 UNUSED_P(systemId);
7979 UNUSED_P(publicId);
7980 if (callno == 0) {
7981 /* Try different allocation levels for whole exercise */
7982 text = ("<!ELEMENT doc (e+)>\n"
7983 "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
7984 "<!ELEMENT e EMPTY>\n");
7985 XML_SetUserData(parser, (void *)(intptr_t)1);
7986 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
7987 if (new_parser == NULL)
7988 return XML_STATUS_ERROR;
7989 rv = _XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE);
7990 } else {
7991 /* Just run through once */
7992 text = ("<?xml version='1.0' encoding='us-ascii'?>"
7993 "<e/>");
7994 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
7995 if (new_parser == NULL)
7996 return XML_STATUS_ERROR;
7997 rv = _XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE);
7998 }
7999 XML_ParserFree(new_parser);
8000 if (rv == XML_STATUS_ERROR)
8001 return XML_STATUS_ERROR;
8002 return XML_STATUS_OK;
8003 }
8004
8005 /* Test more external entity allocation failure paths */
START_TEST(test_alloc_external_entity)8006 START_TEST(test_alloc_external_entity) {
8007 const char *text = "<?xml version='1.0'?>\n"
8008 "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n"
8009 " <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n"
8010 "]>\n"
8011 "<doc xmlns='http://example.org/ns1'>\n"
8012 "&en;\n"
8013 "</doc>";
8014 int i;
8015 const int alloc_test_max_repeats = 50;
8016
8017 for (i = 0; i < alloc_test_max_repeats; i++) {
8018 allocation_count = -1;
8019 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8020 XML_SetExternalEntityRefHandler(g_parser, external_entity_dbl_handler_2);
8021 XML_SetUserData(g_parser, NULL);
8022 allocation_count = i;
8023 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8024 == XML_STATUS_OK)
8025 break;
8026 /* See comment in test_alloc_parse_xdecl() */
8027 alloc_teardown();
8028 alloc_setup();
8029 }
8030 allocation_count = -1;
8031 if (i == 0)
8032 fail("External entity parsed despite duff allocator");
8033 if (i == alloc_test_max_repeats)
8034 fail("External entity not parsed at max allocation count");
8035 }
8036 END_TEST
8037
8038 /* Test more allocation failure paths */
8039 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)8040 external_entity_alloc_set_encoding(XML_Parser parser, const XML_Char *context,
8041 const XML_Char *base,
8042 const XML_Char *systemId,
8043 const XML_Char *publicId) {
8044 /* As for external_entity_loader() */
8045 const char *text = "<?xml encoding='iso-8859-3'?>"
8046 "\xC3\xA9";
8047 XML_Parser ext_parser;
8048 enum XML_Status status;
8049
8050 UNUSED_P(base);
8051 UNUSED_P(systemId);
8052 UNUSED_P(publicId);
8053 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8054 if (ext_parser == NULL)
8055 return XML_STATUS_ERROR;
8056 if (! XML_SetEncoding(ext_parser, XCS("utf-8"))) {
8057 XML_ParserFree(ext_parser);
8058 return XML_STATUS_ERROR;
8059 }
8060 status
8061 = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
8062 XML_ParserFree(ext_parser);
8063 if (status == XML_STATUS_ERROR)
8064 return XML_STATUS_ERROR;
8065 return XML_STATUS_OK;
8066 }
8067
START_TEST(test_alloc_ext_entity_set_encoding)8068 START_TEST(test_alloc_ext_entity_set_encoding) {
8069 const char *text = "<!DOCTYPE doc [\n"
8070 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
8071 "]>\n"
8072 "<doc>&en;</doc>";
8073 int i;
8074 const int max_allocation_count = 30;
8075
8076 for (i = 0; i < max_allocation_count; i++) {
8077 XML_SetExternalEntityRefHandler(g_parser,
8078 external_entity_alloc_set_encoding);
8079 allocation_count = i;
8080 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8081 == XML_STATUS_OK)
8082 break;
8083 allocation_count = -1;
8084 /* See comment in test_alloc_parse_xdecl() */
8085 alloc_teardown();
8086 alloc_setup();
8087 }
8088 if (i == 0)
8089 fail("Encoding check succeeded despite failing allocator");
8090 if (i == max_allocation_count)
8091 fail("Encoding failed at max allocation count");
8092 }
8093 END_TEST
8094
8095 static int XMLCALL
unknown_released_encoding_handler(void * data,const XML_Char * encoding,XML_Encoding * info)8096 unknown_released_encoding_handler(void *data, const XML_Char *encoding,
8097 XML_Encoding *info) {
8098 UNUSED_P(data);
8099 if (! xcstrcmp(encoding, XCS("unsupported-encoding"))) {
8100 int i;
8101
8102 for (i = 0; i < 256; i++)
8103 info->map[i] = i;
8104 info->data = NULL;
8105 info->convert = NULL;
8106 info->release = dummy_release;
8107 return XML_STATUS_OK;
8108 }
8109 return XML_STATUS_ERROR;
8110 }
8111
8112 /* Test the effects of allocation failure in internal entities.
8113 * Based on test_unknown_encoding_internal_entity
8114 */
START_TEST(test_alloc_internal_entity)8115 START_TEST(test_alloc_internal_entity) {
8116 const char *text = "<?xml version='1.0' encoding='unsupported-encoding'?>\n"
8117 "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n"
8118 "<test a='&foo;'/>";
8119 unsigned int i;
8120 const unsigned int max_alloc_count = 20;
8121
8122 for (i = 0; i < max_alloc_count; i++) {
8123 allocation_count = i;
8124 XML_SetUnknownEncodingHandler(g_parser, unknown_released_encoding_handler,
8125 NULL);
8126 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8127 != XML_STATUS_ERROR)
8128 break;
8129 /* See comment in test_alloc_parse_xdecl() */
8130 alloc_teardown();
8131 alloc_setup();
8132 }
8133 if (i == 0)
8134 fail("Internal entity worked despite failing allocations");
8135 else if (i == max_alloc_count)
8136 fail("Internal entity failed at max allocation count");
8137 }
8138 END_TEST
8139
8140 /* Test the robustness against allocation failure of element handling
8141 * Based on test_dtd_default_handling().
8142 */
START_TEST(test_alloc_dtd_default_handling)8143 START_TEST(test_alloc_dtd_default_handling) {
8144 const char *text = "<!DOCTYPE doc [\n"
8145 "<!ENTITY e SYSTEM 'http://example.org/e'>\n"
8146 "<!NOTATION n SYSTEM 'http://example.org/n'>\n"
8147 "<!ENTITY e1 SYSTEM 'http://example.org/e' NDATA n>\n"
8148 "<!ELEMENT doc (#PCDATA)>\n"
8149 "<!ATTLIST doc a CDATA #IMPLIED>\n"
8150 "<?pi in dtd?>\n"
8151 "<!--comment in dtd-->\n"
8152 "]>\n"
8153 "<doc><![CDATA[text in doc]]></doc>";
8154 const XML_Char *expected = XCS("\n\n\n\n\n\n\n\n\n<doc>text in doc</doc>");
8155 CharData storage;
8156 int i;
8157 const int max_alloc_count = 25;
8158
8159 for (i = 0; i < max_alloc_count; i++) {
8160 allocation_count = i;
8161 dummy_handler_flags = 0;
8162 XML_SetDefaultHandler(g_parser, accumulate_characters);
8163 XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_handler,
8164 dummy_end_doctype_handler);
8165 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
8166 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
8167 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
8168 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
8169 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
8170 XML_SetCommentHandler(g_parser, dummy_comment_handler);
8171 XML_SetCdataSectionHandler(g_parser, dummy_start_cdata_handler,
8172 dummy_end_cdata_handler);
8173 XML_SetUnparsedEntityDeclHandler(g_parser,
8174 dummy_unparsed_entity_decl_handler);
8175 CharData_Init(&storage);
8176 XML_SetUserData(g_parser, &storage);
8177 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
8178 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8179 != XML_STATUS_ERROR)
8180 break;
8181 /* See comment in test_alloc_parse_xdecl() */
8182 alloc_teardown();
8183 alloc_setup();
8184 }
8185 if (i == 0)
8186 fail("Default DTD parsed despite allocation failures");
8187 if (i == max_alloc_count)
8188 fail("Default DTD not parsed with maximum alloc count");
8189 CharData_CheckXMLChars(&storage, expected);
8190 if (dummy_handler_flags
8191 != (DUMMY_START_DOCTYPE_HANDLER_FLAG | DUMMY_END_DOCTYPE_HANDLER_FLAG
8192 | DUMMY_ENTITY_DECL_HANDLER_FLAG | DUMMY_NOTATION_DECL_HANDLER_FLAG
8193 | DUMMY_ELEMENT_DECL_HANDLER_FLAG | DUMMY_ATTLIST_DECL_HANDLER_FLAG
8194 | DUMMY_COMMENT_HANDLER_FLAG | DUMMY_PI_HANDLER_FLAG
8195 | DUMMY_START_CDATA_HANDLER_FLAG | DUMMY_END_CDATA_HANDLER_FLAG
8196 | DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG))
8197 fail("Not all handlers were called");
8198 }
8199 END_TEST
8200
8201 /* Test robustness of XML_SetEncoding() with a failing allocator */
START_TEST(test_alloc_explicit_encoding)8202 START_TEST(test_alloc_explicit_encoding) {
8203 int i;
8204 const int max_alloc_count = 5;
8205
8206 for (i = 0; i < max_alloc_count; i++) {
8207 allocation_count = i;
8208 if (XML_SetEncoding(g_parser, XCS("us-ascii")) == XML_STATUS_OK)
8209 break;
8210 }
8211 if (i == 0)
8212 fail("Encoding set despite failing allocator");
8213 else if (i == max_alloc_count)
8214 fail("Encoding not set at max allocation count");
8215 }
8216 END_TEST
8217
8218 /* Test robustness of XML_SetBase against a failing allocator */
START_TEST(test_alloc_set_base)8219 START_TEST(test_alloc_set_base) {
8220 const XML_Char *new_base = XCS("/local/file/name.xml");
8221 int i;
8222 const int max_alloc_count = 5;
8223
8224 for (i = 0; i < max_alloc_count; i++) {
8225 allocation_count = i;
8226 if (XML_SetBase(g_parser, new_base) == XML_STATUS_OK)
8227 break;
8228 }
8229 if (i == 0)
8230 fail("Base set despite failing allocator");
8231 else if (i == max_alloc_count)
8232 fail("Base not set with max allocation count");
8233 }
8234 END_TEST
8235
8236 /* Test buffer extension in the face of a duff reallocator */
START_TEST(test_alloc_realloc_buffer)8237 START_TEST(test_alloc_realloc_buffer) {
8238 const char *text = get_buffer_test_text;
8239 void *buffer;
8240 int i;
8241 const int max_realloc_count = 10;
8242
8243 /* Get a smallish buffer */
8244 for (i = 0; i < max_realloc_count; i++) {
8245 reallocation_count = i;
8246 buffer = XML_GetBuffer(g_parser, 1536);
8247 if (buffer == NULL)
8248 fail("1.5K buffer reallocation failed");
8249 assert(buffer != NULL);
8250 memcpy(buffer, text, strlen(text));
8251 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE)
8252 == XML_STATUS_OK)
8253 break;
8254 /* See comment in test_alloc_parse_xdecl() */
8255 alloc_teardown();
8256 alloc_setup();
8257 }
8258 reallocation_count = -1;
8259 if (i == 0)
8260 fail("Parse succeeded with no reallocation");
8261 else if (i == max_realloc_count)
8262 fail("Parse failed with max reallocation count");
8263 }
8264 END_TEST
8265
8266 /* Same test for external entity parsers */
8267 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)8268 external_entity_reallocator(XML_Parser parser, const XML_Char *context,
8269 const XML_Char *base, const XML_Char *systemId,
8270 const XML_Char *publicId) {
8271 const char *text = get_buffer_test_text;
8272 XML_Parser ext_parser;
8273 void *buffer;
8274 enum XML_Status status;
8275
8276 UNUSED_P(base);
8277 UNUSED_P(systemId);
8278 UNUSED_P(publicId);
8279 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8280 if (ext_parser == NULL)
8281 fail("Could not create external entity parser");
8282
8283 reallocation_count = (intptr_t)XML_GetUserData(parser);
8284 buffer = XML_GetBuffer(ext_parser, 1536);
8285 if (buffer == NULL)
8286 fail("Buffer allocation failed");
8287 assert(buffer != NULL);
8288 memcpy(buffer, text, strlen(text));
8289 status = XML_ParseBuffer(ext_parser, (int)strlen(text), XML_FALSE);
8290 reallocation_count = -1;
8291 XML_ParserFree(ext_parser);
8292 return (status == XML_STATUS_OK) ? XML_STATUS_OK : XML_STATUS_ERROR;
8293 }
8294
START_TEST(test_alloc_ext_entity_realloc_buffer)8295 START_TEST(test_alloc_ext_entity_realloc_buffer) {
8296 const char *text = "<!DOCTYPE doc [\n"
8297 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
8298 "]>\n"
8299 "<doc>&en;</doc>";
8300 int i;
8301 const int max_realloc_count = 10;
8302
8303 for (i = 0; i < max_realloc_count; i++) {
8304 XML_SetExternalEntityRefHandler(g_parser, external_entity_reallocator);
8305 XML_SetUserData(g_parser, (void *)(intptr_t)i);
8306 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8307 == XML_STATUS_OK)
8308 break;
8309 /* See comment in test_alloc_parse_xdecl() */
8310 alloc_teardown();
8311 alloc_setup();
8312 }
8313 if (i == 0)
8314 fail("Succeeded with no reallocations");
8315 if (i == max_realloc_count)
8316 fail("Failed with max reallocations");
8317 }
8318 END_TEST
8319
8320 /* Test elements with many attributes are handled correctly */
START_TEST(test_alloc_realloc_many_attributes)8321 START_TEST(test_alloc_realloc_many_attributes) {
8322 const char *text = "<!DOCTYPE doc [\n"
8323 "<!ATTLIST doc za CDATA 'default'>\n"
8324 "<!ATTLIST doc zb CDATA 'def2'>\n"
8325 "<!ATTLIST doc zc CDATA 'def3'>\n"
8326 "]>\n"
8327 "<doc a='1'"
8328 " b='2'"
8329 " c='3'"
8330 " d='4'"
8331 " e='5'"
8332 " f='6'"
8333 " g='7'"
8334 " h='8'"
8335 " i='9'"
8336 " j='10'"
8337 " k='11'"
8338 " l='12'"
8339 " m='13'"
8340 " n='14'"
8341 " p='15'"
8342 " q='16'"
8343 " r='17'"
8344 " s='18'>"
8345 "</doc>";
8346 int i;
8347 const int max_realloc_count = 10;
8348
8349 for (i = 0; i < max_realloc_count; i++) {
8350 reallocation_count = i;
8351 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8352 != XML_STATUS_ERROR)
8353 break;
8354 /* See comment in test_alloc_parse_xdecl() */
8355 alloc_teardown();
8356 alloc_setup();
8357 }
8358 if (i == 0)
8359 fail("Parse succeeded despite no reallocations");
8360 if (i == max_realloc_count)
8361 fail("Parse failed at max reallocations");
8362 }
8363 END_TEST
8364
8365 /* Test handling of a public entity with failing allocator */
START_TEST(test_alloc_public_entity_value)8366 START_TEST(test_alloc_public_entity_value) {
8367 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
8368 "<doc></doc>\n";
8369 char dtd_text[]
8370 = "<!ELEMENT doc EMPTY>\n"
8371 "<!ENTITY % e1 PUBLIC 'foo' 'bar.ent'>\n"
8372 "<!ENTITY % "
8373 /* Each line is 64 characters */
8374 "ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345"
8375 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8376 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8377 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8378 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8379 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8380 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8381 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8382 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8383 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8384 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8385 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8386 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8387 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8388 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8389 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8390 " '%e1;'>\n"
8391 "%e1;\n";
8392 int i;
8393 const int max_alloc_count = 50;
8394
8395 for (i = 0; i < max_alloc_count; i++) {
8396 allocation_count = i;
8397 dummy_handler_flags = 0;
8398 XML_SetUserData(g_parser, dtd_text);
8399 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8400 XML_SetExternalEntityRefHandler(g_parser, external_entity_public);
8401 /* Provoke a particular code path */
8402 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
8403 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8404 != XML_STATUS_ERROR)
8405 break;
8406 /* See comment in test_alloc_parse_xdecl() */
8407 alloc_teardown();
8408 alloc_setup();
8409 }
8410 if (i == 0)
8411 fail("Parsing worked despite failing allocation");
8412 if (i == max_alloc_count)
8413 fail("Parsing failed at max allocation count");
8414 if (dummy_handler_flags != DUMMY_ENTITY_DECL_HANDLER_FLAG)
8415 fail("Entity declaration handler not called");
8416 }
8417 END_TEST
8418
START_TEST(test_alloc_realloc_subst_public_entity_value)8419 START_TEST(test_alloc_realloc_subst_public_entity_value) {
8420 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
8421 "<doc></doc>\n";
8422 char dtd_text[]
8423 = "<!ELEMENT doc EMPTY>\n"
8424 "<!ENTITY % "
8425 /* Each line is 64 characters */
8426 "ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345"
8427 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
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 " PUBLIC 'foo' 'bar.ent'>\n"
8443 "%ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345"
8444 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8445 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8446 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8447 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8448 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8449 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8450 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8451 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8452 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8453 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8454 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8455 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8456 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8457 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8458 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP;";
8459 int i;
8460 const int max_realloc_count = 10;
8461
8462 for (i = 0; i < max_realloc_count; i++) {
8463 reallocation_count = i;
8464 XML_SetUserData(g_parser, dtd_text);
8465 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8466 XML_SetExternalEntityRefHandler(g_parser, external_entity_public);
8467 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8468 != XML_STATUS_ERROR)
8469 break;
8470 /* See comment in test_alloc_parse_xdecl() */
8471 alloc_teardown();
8472 alloc_setup();
8473 }
8474 if (i == 0)
8475 fail("Parsing worked despite failing reallocation");
8476 if (i == max_realloc_count)
8477 fail("Parsing failed at max reallocation count");
8478 }
8479 END_TEST
8480
START_TEST(test_alloc_parse_public_doctype)8481 START_TEST(test_alloc_parse_public_doctype) {
8482 const char *text
8483 = "<?xml version='1.0' encoding='utf-8'?>\n"
8484 "<!DOCTYPE doc PUBLIC '"
8485 /* 64 characters per line */
8486 "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/"
8487 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8488 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8489 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8490 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8491 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8492 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8493 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8494 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8495 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8496 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8497 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8498 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8499 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8500 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8501 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8502 "' 'test'>\n"
8503 "<doc></doc>";
8504 int i;
8505 const int max_alloc_count = 25;
8506
8507 for (i = 0; i < max_alloc_count; i++) {
8508 allocation_count = i;
8509 dummy_handler_flags = 0;
8510 XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_decl_handler,
8511 dummy_end_doctype_decl_handler);
8512 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8513 != XML_STATUS_ERROR)
8514 break;
8515 /* See comment in test_alloc_parse_xdecl() */
8516 alloc_teardown();
8517 alloc_setup();
8518 }
8519 if (i == 0)
8520 fail("Parse succeeded despite failing allocator");
8521 if (i == max_alloc_count)
8522 fail("Parse failed at maximum allocation count");
8523 if (dummy_handler_flags
8524 != (DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG
8525 | DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG))
8526 fail("Doctype handler functions not called");
8527 }
8528 END_TEST
8529
START_TEST(test_alloc_parse_public_doctype_long_name)8530 START_TEST(test_alloc_parse_public_doctype_long_name) {
8531 const char *text
8532 = "<?xml version='1.0' encoding='utf-8'?>\n"
8533 "<!DOCTYPE doc PUBLIC 'http://example.com/foo' '"
8534 /* 64 characters per line */
8535 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8536 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8537 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8538 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8539 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8540 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8541 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8542 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8543 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8544 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8545 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8546 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8547 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8548 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8549 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8550 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8551 "'>\n"
8552 "<doc></doc>";
8553 int i;
8554 const int max_alloc_count = 25;
8555
8556 for (i = 0; i < max_alloc_count; i++) {
8557 allocation_count = i;
8558 XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_decl_handler,
8559 dummy_end_doctype_decl_handler);
8560 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8561 != XML_STATUS_ERROR)
8562 break;
8563 /* See comment in test_alloc_parse_xdecl() */
8564 alloc_teardown();
8565 alloc_setup();
8566 }
8567 if (i == 0)
8568 fail("Parse succeeded despite failing allocator");
8569 if (i == max_alloc_count)
8570 fail("Parse failed at maximum allocation count");
8571 }
8572 END_TEST
8573
8574 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)8575 external_entity_alloc(XML_Parser parser, const XML_Char *context,
8576 const XML_Char *base, const XML_Char *systemId,
8577 const XML_Char *publicId) {
8578 const char *text = (const char *)XML_GetUserData(parser);
8579 XML_Parser ext_parser;
8580 int parse_res;
8581
8582 UNUSED_P(base);
8583 UNUSED_P(systemId);
8584 UNUSED_P(publicId);
8585 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8586 if (ext_parser == NULL)
8587 return XML_STATUS_ERROR;
8588 parse_res
8589 = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
8590 XML_ParserFree(ext_parser);
8591 return parse_res;
8592 }
8593
8594 /* Test foreign DTD handling */
START_TEST(test_alloc_set_foreign_dtd)8595 START_TEST(test_alloc_set_foreign_dtd) {
8596 const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n"
8597 "<doc>&entity;</doc>";
8598 char text2[] = "<!ELEMENT doc (#PCDATA)*>";
8599 int i;
8600 const int max_alloc_count = 25;
8601
8602 for (i = 0; i < max_alloc_count; i++) {
8603 allocation_count = i;
8604 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8605 XML_SetUserData(g_parser, &text2);
8606 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
8607 if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE)
8608 fail("Could not set foreign DTD");
8609 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_TRUE)
8610 != XML_STATUS_ERROR)
8611 break;
8612 /* See comment in test_alloc_parse_xdecl() */
8613 alloc_teardown();
8614 alloc_setup();
8615 }
8616 if (i == 0)
8617 fail("Parse succeeded despite failing allocator");
8618 if (i == max_alloc_count)
8619 fail("Parse failed at maximum allocation count");
8620 }
8621 END_TEST
8622
8623 /* Test based on ibm/valid/P32/ibm32v04.xml */
START_TEST(test_alloc_attribute_enum_value)8624 START_TEST(test_alloc_attribute_enum_value) {
8625 const char *text = "<?xml version='1.0' standalone='no'?>\n"
8626 "<!DOCTYPE animal SYSTEM 'test.dtd'>\n"
8627 "<animal>This is a \n <a/> \n\nyellow tiger</animal>";
8628 char dtd_text[] = "<!ELEMENT animal (#PCDATA|a)*>\n"
8629 "<!ELEMENT a EMPTY>\n"
8630 "<!ATTLIST animal xml:space (default|preserve) 'preserve'>";
8631 int i;
8632 const int max_alloc_count = 30;
8633
8634 for (i = 0; i < max_alloc_count; i++) {
8635 allocation_count = i;
8636 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
8637 XML_SetUserData(g_parser, dtd_text);
8638 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8639 /* An attribute list handler provokes a different code path */
8640 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
8641 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8642 != XML_STATUS_ERROR)
8643 break;
8644 /* See comment in test_alloc_parse_xdecl() */
8645 alloc_teardown();
8646 alloc_setup();
8647 }
8648 if (i == 0)
8649 fail("Parse succeeded despite failing allocator");
8650 if (i == max_alloc_count)
8651 fail("Parse failed at maximum allocation count");
8652 }
8653 END_TEST
8654
8655 /* Test attribute enums sufficient to overflow the string pool */
START_TEST(test_alloc_realloc_attribute_enum_value)8656 START_TEST(test_alloc_realloc_attribute_enum_value) {
8657 const char *text = "<?xml version='1.0' standalone='no'?>\n"
8658 "<!DOCTYPE animal SYSTEM 'test.dtd'>\n"
8659 "<animal>This is a yellow tiger</animal>";
8660 /* We wish to define a collection of attribute enums that will
8661 * cause the string pool storing them to have to expand. This
8662 * means more than 1024 bytes, including the parentheses and
8663 * separator bars.
8664 */
8665 char dtd_text[]
8666 = "<!ELEMENT animal (#PCDATA)*>\n"
8667 "<!ATTLIST animal thing "
8668 "(default"
8669 /* Each line is 64 characters */
8670 "|ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8671 "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8672 "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8673 "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8674 "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8675 "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8676 "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8677 "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8678 "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8679 "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8680 "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8681 "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8682 "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8683 "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8684 "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8685 "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO)"
8686 " 'default'>";
8687 int i;
8688 const int max_realloc_count = 10;
8689
8690 for (i = 0; i < max_realloc_count; i++) {
8691 reallocation_count = i;
8692 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
8693 XML_SetUserData(g_parser, dtd_text);
8694 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8695 /* An attribute list handler provokes a different code path */
8696 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
8697 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8698 != XML_STATUS_ERROR)
8699 break;
8700 /* See comment in test_alloc_parse_xdecl() */
8701 alloc_teardown();
8702 alloc_setup();
8703 }
8704 if (i == 0)
8705 fail("Parse succeeded despite failing reallocator");
8706 if (i == max_realloc_count)
8707 fail("Parse failed at maximum reallocation count");
8708 }
8709 END_TEST
8710
8711 /* Test attribute enums in a #IMPLIED attribute forcing pool growth */
START_TEST(test_alloc_realloc_implied_attribute)8712 START_TEST(test_alloc_realloc_implied_attribute) {
8713 /* Forcing this particular code path is a balancing act. The
8714 * addition of the closing parenthesis and terminal NUL must be
8715 * what pushes the string of enums over the 1024-byte limit,
8716 * otherwise a different code path will pick up the realloc.
8717 */
8718 const char *text
8719 = "<!DOCTYPE doc [\n"
8720 "<!ELEMENT doc EMPTY>\n"
8721 "<!ATTLIST doc a "
8722 /* Each line is 64 characters */
8723 "(ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8724 "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8725 "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8726 "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8727 "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8728 "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8729 "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8730 "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8731 "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8732 "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8733 "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8734 "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8735 "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8736 "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8737 "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8738 "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN)"
8739 " #IMPLIED>\n"
8740 "]><doc/>";
8741 int i;
8742 const int max_realloc_count = 10;
8743
8744 for (i = 0; i < max_realloc_count; i++) {
8745 reallocation_count = i;
8746 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
8747 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8748 != XML_STATUS_ERROR)
8749 break;
8750 /* See comment in test_alloc_parse_xdecl() */
8751 alloc_teardown();
8752 alloc_setup();
8753 }
8754 if (i == 0)
8755 fail("Parse succeeded despite failing reallocator");
8756 if (i == max_realloc_count)
8757 fail("Parse failed at maximum reallocation count");
8758 }
8759 END_TEST
8760
8761 /* Test attribute enums in a defaulted attribute forcing pool growth */
START_TEST(test_alloc_realloc_default_attribute)8762 START_TEST(test_alloc_realloc_default_attribute) {
8763 /* Forcing this particular code path is a balancing act. The
8764 * addition of the closing parenthesis and terminal NUL must be
8765 * what pushes the string of enums over the 1024-byte limit,
8766 * otherwise a different code path will pick up the realloc.
8767 */
8768 const char *text
8769 = "<!DOCTYPE doc [\n"
8770 "<!ELEMENT doc EMPTY>\n"
8771 "<!ATTLIST doc a "
8772 /* Each line is 64 characters */
8773 "(ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8774 "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8775 "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8776 "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8777 "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8778 "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8779 "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8780 "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8781 "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8782 "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8783 "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8784 "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8785 "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8786 "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8787 "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8788 "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN)"
8789 " 'ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO'"
8790 ">\n]><doc/>";
8791 int i;
8792 const int max_realloc_count = 10;
8793
8794 for (i = 0; i < max_realloc_count; i++) {
8795 reallocation_count = i;
8796 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
8797 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8798 != XML_STATUS_ERROR)
8799 break;
8800 /* See comment in test_alloc_parse_xdecl() */
8801 alloc_teardown();
8802 alloc_setup();
8803 }
8804 if (i == 0)
8805 fail("Parse succeeded despite failing reallocator");
8806 if (i == max_realloc_count)
8807 fail("Parse failed at maximum reallocation count");
8808 }
8809 END_TEST
8810
8811 /* Test long notation name with dodgy allocator */
START_TEST(test_alloc_notation)8812 START_TEST(test_alloc_notation) {
8813 const char *text
8814 = "<!DOCTYPE doc [\n"
8815 "<!NOTATION "
8816 /* Each line is 64 characters */
8817 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8818 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
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 " SYSTEM 'http://example.org/n'>\n"
8834 "<!ENTITY e SYSTEM 'http://example.org/e' NDATA "
8835 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8836 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8837 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8838 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8839 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8840 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8841 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8842 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8843 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8844 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8845 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8846 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8847 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8848 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8849 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8850 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8851 ">\n"
8852 "<!ELEMENT doc EMPTY>\n"
8853 "]>\n<doc/>";
8854 int i;
8855 const int max_alloc_count = 20;
8856
8857 for (i = 0; i < max_alloc_count; i++) {
8858 allocation_count = i;
8859 dummy_handler_flags = 0;
8860 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
8861 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
8862 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8863 != XML_STATUS_ERROR)
8864 break;
8865 /* See comment in test_alloc_parse_xdecl() */
8866 alloc_teardown();
8867 alloc_setup();
8868 }
8869 if (i == 0)
8870 fail("Parse succeeded despite allocation failures");
8871 if (i == max_alloc_count)
8872 fail("Parse failed at maximum allocation count");
8873 if (dummy_handler_flags
8874 != (DUMMY_ENTITY_DECL_HANDLER_FLAG | DUMMY_NOTATION_DECL_HANDLER_FLAG))
8875 fail("Entity declaration handler not called");
8876 }
8877 END_TEST
8878
8879 /* Test public notation with dodgy allocator */
START_TEST(test_alloc_public_notation)8880 START_TEST(test_alloc_public_notation) {
8881 const char *text
8882 = "<!DOCTYPE doc [\n"
8883 "<!NOTATION note PUBLIC '"
8884 /* 64 characters per line */
8885 "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/"
8886 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8887 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8888 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8889 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8890 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8891 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8892 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8893 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8894 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8895 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8896 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8897 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8898 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8899 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8900 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8901 "' 'foo'>\n"
8902 "<!ENTITY e SYSTEM 'http://example.com/e' NDATA note>\n"
8903 "<!ELEMENT doc EMPTY>\n"
8904 "]>\n<doc/>";
8905 int i;
8906 const int max_alloc_count = 20;
8907
8908 for (i = 0; i < max_alloc_count; i++) {
8909 allocation_count = i;
8910 dummy_handler_flags = 0;
8911 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
8912 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8913 != XML_STATUS_ERROR)
8914 break;
8915 /* See comment in test_alloc_parse_xdecl() */
8916 alloc_teardown();
8917 alloc_setup();
8918 }
8919 if (i == 0)
8920 fail("Parse succeeded despite allocation failures");
8921 if (i == max_alloc_count)
8922 fail("Parse failed at maximum allocation count");
8923 if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG)
8924 fail("Notation handler not called");
8925 }
8926 END_TEST
8927
8928 /* Test public notation with dodgy allocator */
START_TEST(test_alloc_system_notation)8929 START_TEST(test_alloc_system_notation) {
8930 const char *text
8931 = "<!DOCTYPE doc [\n"
8932 "<!NOTATION note SYSTEM '"
8933 /* 64 characters per line */
8934 "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/"
8935 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8936 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8937 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8938 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8939 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8940 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8941 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8942 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8943 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8944 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8945 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8946 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8947 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8948 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8949 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8950 "'>\n"
8951 "<!ENTITY e SYSTEM 'http://example.com/e' NDATA note>\n"
8952 "<!ELEMENT doc EMPTY>\n"
8953 "]>\n<doc/>";
8954 int i;
8955 const int max_alloc_count = 20;
8956
8957 for (i = 0; i < max_alloc_count; i++) {
8958 allocation_count = i;
8959 dummy_handler_flags = 0;
8960 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
8961 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8962 != XML_STATUS_ERROR)
8963 break;
8964 /* See comment in test_alloc_parse_xdecl() */
8965 alloc_teardown();
8966 alloc_setup();
8967 }
8968 if (i == 0)
8969 fail("Parse succeeded despite allocation failures");
8970 if (i == max_alloc_count)
8971 fail("Parse failed at maximum allocation count");
8972 if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG)
8973 fail("Notation handler not called");
8974 }
8975 END_TEST
8976
START_TEST(test_alloc_nested_groups)8977 START_TEST(test_alloc_nested_groups) {
8978 const char *text
8979 = "<!DOCTYPE doc [\n"
8980 "<!ELEMENT doc "
8981 /* Sixteen elements per line */
8982 "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,"
8983 "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?"
8984 "))))))))))))))))))))))))))))))))>\n"
8985 "<!ELEMENT e EMPTY>"
8986 "]>\n"
8987 "<doc><e/></doc>";
8988 CharData storage;
8989 int i;
8990 const int max_alloc_count = 20;
8991
8992 for (i = 0; i < max_alloc_count; i++) {
8993 allocation_count = i;
8994 CharData_Init(&storage);
8995 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
8996 XML_SetStartElementHandler(g_parser, record_element_start_handler);
8997 XML_SetUserData(g_parser, &storage);
8998 dummy_handler_flags = 0;
8999 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9000 != XML_STATUS_ERROR)
9001 break;
9002 /* See comment in test_alloc_parse_xdecl() */
9003 alloc_teardown();
9004 alloc_setup();
9005 }
9006
9007 if (i == 0)
9008 fail("Parse succeeded despite failing reallocator");
9009 if (i == max_alloc_count)
9010 fail("Parse failed at maximum reallocation count");
9011 CharData_CheckXMLChars(&storage, XCS("doce"));
9012 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9013 fail("Element handler not fired");
9014 }
9015 END_TEST
9016
START_TEST(test_alloc_realloc_nested_groups)9017 START_TEST(test_alloc_realloc_nested_groups) {
9018 const char *text
9019 = "<!DOCTYPE doc [\n"
9020 "<!ELEMENT doc "
9021 /* Sixteen elements per line */
9022 "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,"
9023 "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?"
9024 "))))))))))))))))))))))))))))))))>\n"
9025 "<!ELEMENT e EMPTY>"
9026 "]>\n"
9027 "<doc><e/></doc>";
9028 CharData storage;
9029 int i;
9030 const int max_realloc_count = 10;
9031
9032 for (i = 0; i < max_realloc_count; i++) {
9033 reallocation_count = i;
9034 CharData_Init(&storage);
9035 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
9036 XML_SetStartElementHandler(g_parser, record_element_start_handler);
9037 XML_SetUserData(g_parser, &storage);
9038 dummy_handler_flags = 0;
9039 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9040 != XML_STATUS_ERROR)
9041 break;
9042 /* See comment in test_alloc_parse_xdecl() */
9043 alloc_teardown();
9044 alloc_setup();
9045 }
9046
9047 if (i == 0)
9048 fail("Parse succeeded despite failing reallocator");
9049 if (i == max_realloc_count)
9050 fail("Parse failed at maximum reallocation count");
9051 CharData_CheckXMLChars(&storage, XCS("doce"));
9052 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9053 fail("Element handler not fired");
9054 }
9055 END_TEST
9056
START_TEST(test_alloc_large_group)9057 START_TEST(test_alloc_large_group) {
9058 const char *text = "<!DOCTYPE doc [\n"
9059 "<!ELEMENT doc ("
9060 "a1|a2|a3|a4|a5|a6|a7|a8|"
9061 "b1|b2|b3|b4|b5|b6|b7|b8|"
9062 "c1|c2|c3|c4|c5|c6|c7|c8|"
9063 "d1|d2|d3|d4|d5|d6|d7|d8|"
9064 "e1"
9065 ")+>\n"
9066 "]>\n"
9067 "<doc>\n"
9068 "<a1/>\n"
9069 "</doc>\n";
9070 int i;
9071 const int max_alloc_count = 50;
9072
9073 for (i = 0; i < max_alloc_count; i++) {
9074 allocation_count = i;
9075 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
9076 dummy_handler_flags = 0;
9077 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9078 != XML_STATUS_ERROR)
9079 break;
9080 /* See comment in test_alloc_parse_xdecl() */
9081 alloc_teardown();
9082 alloc_setup();
9083 }
9084 if (i == 0)
9085 fail("Parse succeeded despite failing allocator");
9086 if (i == max_alloc_count)
9087 fail("Parse failed at maximum allocation count");
9088 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9089 fail("Element handler flag not raised");
9090 }
9091 END_TEST
9092
START_TEST(test_alloc_realloc_group_choice)9093 START_TEST(test_alloc_realloc_group_choice) {
9094 const char *text = "<!DOCTYPE doc [\n"
9095 "<!ELEMENT doc ("
9096 "a1|a2|a3|a4|a5|a6|a7|a8|"
9097 "b1|b2|b3|b4|b5|b6|b7|b8|"
9098 "c1|c2|c3|c4|c5|c6|c7|c8|"
9099 "d1|d2|d3|d4|d5|d6|d7|d8|"
9100 "e1"
9101 ")+>\n"
9102 "]>\n"
9103 "<doc>\n"
9104 "<a1/>\n"
9105 "<b2 attr='foo'>This is a foo</b2>\n"
9106 "<c3></c3>\n"
9107 "</doc>\n";
9108 int i;
9109 const int max_realloc_count = 10;
9110
9111 for (i = 0; i < max_realloc_count; i++) {
9112 reallocation_count = i;
9113 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
9114 dummy_handler_flags = 0;
9115 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9116 != XML_STATUS_ERROR)
9117 break;
9118 /* See comment in test_alloc_parse_xdecl() */
9119 alloc_teardown();
9120 alloc_setup();
9121 }
9122 if (i == 0)
9123 fail("Parse succeeded despite failing reallocator");
9124 if (i == max_realloc_count)
9125 fail("Parse failed at maximum reallocation count");
9126 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9127 fail("Element handler flag not raised");
9128 }
9129 END_TEST
9130
START_TEST(test_alloc_pi_in_epilog)9131 START_TEST(test_alloc_pi_in_epilog) {
9132 const char *text = "<doc></doc>\n"
9133 "<?pi in epilog?>";
9134 int i;
9135 const int max_alloc_count = 15;
9136
9137 for (i = 0; i < max_alloc_count; i++) {
9138 allocation_count = i;
9139 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
9140 dummy_handler_flags = 0;
9141 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9142 != XML_STATUS_ERROR)
9143 break;
9144 /* See comment in test_alloc_parse_xdecl() */
9145 alloc_teardown();
9146 alloc_setup();
9147 }
9148 if (i == 0)
9149 fail("Parse completed despite failing allocator");
9150 if (i == max_alloc_count)
9151 fail("Parse failed at maximum allocation count");
9152 if (dummy_handler_flags != DUMMY_PI_HANDLER_FLAG)
9153 fail("Processing instruction handler not invoked");
9154 }
9155 END_TEST
9156
START_TEST(test_alloc_comment_in_epilog)9157 START_TEST(test_alloc_comment_in_epilog) {
9158 const char *text = "<doc></doc>\n"
9159 "<!-- comment in epilog -->";
9160 int i;
9161 const int max_alloc_count = 15;
9162
9163 for (i = 0; i < max_alloc_count; i++) {
9164 allocation_count = i;
9165 XML_SetCommentHandler(g_parser, dummy_comment_handler);
9166 dummy_handler_flags = 0;
9167 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9168 != XML_STATUS_ERROR)
9169 break;
9170 /* See comment in test_alloc_parse_xdecl() */
9171 alloc_teardown();
9172 alloc_setup();
9173 }
9174 if (i == 0)
9175 fail("Parse completed despite failing allocator");
9176 if (i == max_alloc_count)
9177 fail("Parse failed at maximum allocation count");
9178 if (dummy_handler_flags != DUMMY_COMMENT_HANDLER_FLAG)
9179 fail("Processing instruction handler not invoked");
9180 }
9181 END_TEST
9182
START_TEST(test_alloc_realloc_long_attribute_value)9183 START_TEST(test_alloc_realloc_long_attribute_value) {
9184 const char *text
9185 = "<!DOCTYPE doc [<!ENTITY foo '"
9186 /* Each line is 64 characters */
9187 "This entity will be substituted as an attribute value, and is "
9188 "calculated to be exactly long enough that the terminating NUL "
9189 "that the library adds internally will trigger the string pool to"
9190 "grow. GHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9191 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9192 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9193 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9194 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9195 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9196 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9197 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9198 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9199 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9200 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9201 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9202 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9203 "'>]>\n"
9204 "<doc a='&foo;'></doc>";
9205 int i;
9206 const int max_realloc_count = 10;
9207
9208 for (i = 0; i < max_realloc_count; i++) {
9209 reallocation_count = i;
9210 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9211 != XML_STATUS_ERROR)
9212 break;
9213 /* See comment in test_alloc_parse_xdecl() */
9214 alloc_teardown();
9215 alloc_setup();
9216 }
9217 if (i == 0)
9218 fail("Parse succeeded despite failing reallocator");
9219 if (i == max_realloc_count)
9220 fail("Parse failed at maximum reallocation count");
9221 }
9222 END_TEST
9223
START_TEST(test_alloc_attribute_whitespace)9224 START_TEST(test_alloc_attribute_whitespace) {
9225 const char *text = "<doc a=' '></doc>";
9226 int i;
9227 const int max_alloc_count = 15;
9228
9229 for (i = 0; i < max_alloc_count; i++) {
9230 allocation_count = i;
9231 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9232 != XML_STATUS_ERROR)
9233 break;
9234 /* See comment in test_alloc_parse_xdecl() */
9235 alloc_teardown();
9236 alloc_setup();
9237 }
9238 if (i == 0)
9239 fail("Parse succeeded despite failing allocator");
9240 if (i == max_alloc_count)
9241 fail("Parse failed at maximum allocation count");
9242 }
9243 END_TEST
9244
START_TEST(test_alloc_attribute_predefined_entity)9245 START_TEST(test_alloc_attribute_predefined_entity) {
9246 const char *text = "<doc a='&'></doc>";
9247 int i;
9248 const int max_alloc_count = 15;
9249
9250 for (i = 0; i < max_alloc_count; i++) {
9251 allocation_count = i;
9252 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9253 != XML_STATUS_ERROR)
9254 break;
9255 /* See comment in test_alloc_parse_xdecl() */
9256 alloc_teardown();
9257 alloc_setup();
9258 }
9259 if (i == 0)
9260 fail("Parse succeeded despite failing allocator");
9261 if (i == max_alloc_count)
9262 fail("Parse failed at maximum allocation count");
9263 }
9264 END_TEST
9265
9266 /* Test that a character reference at the end of a suitably long
9267 * default value for an attribute can trigger pool growth, and recovers
9268 * if the allocator fails on it.
9269 */
START_TEST(test_alloc_long_attr_default_with_char_ref)9270 START_TEST(test_alloc_long_attr_default_with_char_ref) {
9271 const char *text
9272 = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '"
9273 /* 64 characters per line */
9274 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9275 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9276 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9277 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9278 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9279 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9280 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9281 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9282 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9283 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9284 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9285 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9286 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9287 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9288 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9289 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHI"
9290 "1'>]>\n"
9291 "<doc/>";
9292 int i;
9293 const int max_alloc_count = 20;
9294
9295 for (i = 0; i < max_alloc_count; i++) {
9296 allocation_count = i;
9297 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9298 != XML_STATUS_ERROR)
9299 break;
9300 /* See comment in test_alloc_parse_xdecl() */
9301 alloc_teardown();
9302 alloc_setup();
9303 }
9304 if (i == 0)
9305 fail("Parse succeeded despite failing allocator");
9306 if (i == max_alloc_count)
9307 fail("Parse failed at maximum allocation count");
9308 }
9309 END_TEST
9310
9311 /* Test that a long character reference substitution triggers a pool
9312 * expansion correctly for an attribute value.
9313 */
START_TEST(test_alloc_long_attr_value)9314 START_TEST(test_alloc_long_attr_value) {
9315 const char *text
9316 = "<!DOCTYPE test [<!ENTITY foo '\n"
9317 /* 64 characters per line */
9318 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9319 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9320 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9321 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9322 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9323 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9324 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9325 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9326 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9327 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9328 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9329 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9330 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9331 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9332 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9333 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9334 "'>]>\n"
9335 "<test a='&foo;'/>";
9336 int i;
9337 const int max_alloc_count = 25;
9338
9339 for (i = 0; i < max_alloc_count; i++) {
9340 allocation_count = i;
9341 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9342 != XML_STATUS_ERROR)
9343 break;
9344 /* See comment in test_alloc_parse_xdecl() */
9345 alloc_teardown();
9346 alloc_setup();
9347 }
9348 if (i == 0)
9349 fail("Parse succeeded despite failing allocator");
9350 if (i == max_alloc_count)
9351 fail("Parse failed at maximum allocation count");
9352 }
9353 END_TEST
9354
9355 /* Test that an error in a nested parameter entity substitution is
9356 * handled correctly. It seems unlikely that the code path being
9357 * exercised can be reached purely by carefully crafted XML, but an
9358 * allocation error in the right place will definitely do it.
9359 */
START_TEST(test_alloc_nested_entities)9360 START_TEST(test_alloc_nested_entities) {
9361 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n"
9362 "<doc />";
9363 ExtFaults test_data
9364 = {"<!ENTITY % pe1 '"
9365 /* 64 characters per line */
9366 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9367 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9368 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9369 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9370 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9371 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9372 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9373 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9374 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9375 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9376 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9377 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9378 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9379 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9380 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9381 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9382 "'>\n"
9383 "<!ENTITY % pe2 '%pe1;'>\n"
9384 "%pe2;",
9385 "Memory Fail not faulted", NULL, XML_ERROR_NO_MEMORY};
9386
9387 /* Causes an allocation error in a nested storeEntityValue() */
9388 allocation_count = 12;
9389 XML_SetUserData(g_parser, &test_data);
9390 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9391 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
9392 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
9393 "Entity allocation failure not noted");
9394 }
9395 END_TEST
9396
START_TEST(test_alloc_realloc_param_entity_newline)9397 START_TEST(test_alloc_realloc_param_entity_newline) {
9398 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
9399 "<doc/>";
9400 char dtd_text[]
9401 = "<!ENTITY % pe '<!ATTLIST doc att CDATA \""
9402 /* 64 characters per line */
9403 "This default value is carefully crafted so that the carriage "
9404 "return right at the end of the entity string causes an internal "
9405 "string pool to have to grow. This allows us to test the alloc "
9406 "failure path from that point. OPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9407 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9408 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9409 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9410 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9411 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9412 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9413 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9414 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9415 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9416 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9417 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9418 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDE"
9419 "\">\n'>"
9420 "%pe;\n";
9421 int i;
9422 const int max_realloc_count = 5;
9423
9424 for (i = 0; i < max_realloc_count; i++) {
9425 reallocation_count = i;
9426 XML_SetUserData(g_parser, dtd_text);
9427 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9428 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9429 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9430 != XML_STATUS_ERROR)
9431 break;
9432 /* See comment in test_alloc_parse_xdecl() */
9433 alloc_teardown();
9434 alloc_setup();
9435 }
9436 if (i == 0)
9437 fail("Parse succeeded despite failing reallocator");
9438 if (i == max_realloc_count)
9439 fail("Parse failed at maximum reallocation count");
9440 }
9441 END_TEST
9442
START_TEST(test_alloc_realloc_ce_extends_pe)9443 START_TEST(test_alloc_realloc_ce_extends_pe) {
9444 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
9445 "<doc/>";
9446 char dtd_text[]
9447 = "<!ENTITY % pe '<!ATTLIST doc att CDATA \""
9448 /* 64 characters per line */
9449 "This default value is carefully crafted so that the character "
9450 "entity at the end causes an internal string pool to have to "
9451 "grow. This allows us to test the allocation failure path from "
9452 "that point onwards. EFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9453 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9454 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9455 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9456 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9457 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9458 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9459 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9460 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9461 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9462 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9463 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9464 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGQ"
9465 "\">\n'>"
9466 "%pe;\n";
9467 int i;
9468 const int max_realloc_count = 5;
9469
9470 for (i = 0; i < max_realloc_count; i++) {
9471 reallocation_count = i;
9472 XML_SetUserData(g_parser, dtd_text);
9473 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9474 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9475 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9476 != XML_STATUS_ERROR)
9477 break;
9478 /* See comment in test_alloc_parse_xdecl() */
9479 alloc_teardown();
9480 alloc_setup();
9481 }
9482 if (i == 0)
9483 fail("Parse succeeded despite failing reallocator");
9484 if (i == max_realloc_count)
9485 fail("Parse failed at maximum reallocation count");
9486 }
9487 END_TEST
9488
START_TEST(test_alloc_realloc_attributes)9489 START_TEST(test_alloc_realloc_attributes) {
9490 const char *text = "<!DOCTYPE doc [\n"
9491 " <!ATTLIST doc\n"
9492 " a1 (a|b|c) 'a'\n"
9493 " a2 (foo|bar) #IMPLIED\n"
9494 " a3 NMTOKEN #IMPLIED\n"
9495 " a4 NMTOKENS #IMPLIED\n"
9496 " a5 ID #IMPLIED\n"
9497 " a6 IDREF #IMPLIED\n"
9498 " a7 IDREFS #IMPLIED\n"
9499 " a8 ENTITY #IMPLIED\n"
9500 " a9 ENTITIES #IMPLIED\n"
9501 " a10 CDATA #IMPLIED\n"
9502 " >]>\n"
9503 "<doc>wombat</doc>\n";
9504 int i;
9505 const int max_realloc_count = 5;
9506
9507 for (i = 0; i < max_realloc_count; i++) {
9508 reallocation_count = i;
9509 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9510 != XML_STATUS_ERROR)
9511 break;
9512 /* See comment in test_alloc_parse_xdecl() */
9513 alloc_teardown();
9514 alloc_setup();
9515 }
9516
9517 if (i == 0)
9518 fail("Parse succeeded despite failing reallocator");
9519 if (i == max_realloc_count)
9520 fail("Parse failed at maximum reallocation count");
9521 }
9522 END_TEST
9523
START_TEST(test_alloc_long_doc_name)9524 START_TEST(test_alloc_long_doc_name) {
9525 const char *text =
9526 /* 64 characters per line */
9527 "<LongRootElementNameThatWillCauseTheNextAllocationToExpandTheStr"
9528 "ingPoolForTheDTDQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9529 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9530 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9531 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9532 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9533 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9534 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9535 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9536 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9537 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9538 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9539 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9540 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9541 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9542 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9543 " a='1'/>";
9544 int i;
9545 const int max_alloc_count = 20;
9546
9547 for (i = 0; i < max_alloc_count; i++) {
9548 allocation_count = i;
9549 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9550 != XML_STATUS_ERROR)
9551 break;
9552 /* See comment in test_alloc_parse_xdecl() */
9553 alloc_teardown();
9554 alloc_setup();
9555 }
9556 if (i == 0)
9557 fail("Parsing worked despite failing reallocations");
9558 else if (i == max_alloc_count)
9559 fail("Parsing failed even at max reallocation count");
9560 }
9561 END_TEST
9562
START_TEST(test_alloc_long_base)9563 START_TEST(test_alloc_long_base) {
9564 const char *text = "<!DOCTYPE doc [\n"
9565 " <!ENTITY e SYSTEM 'foo'>\n"
9566 "]>\n"
9567 "<doc>&e;</doc>";
9568 char entity_text[] = "Hello world";
9569 const XML_Char *base =
9570 /* 64 characters per line */
9571 /* clang-format off */
9572 XCS("LongBaseURI/that/will/overflow/an/internal/buffer/and/cause/it/t")
9573 XCS("o/have/to/grow/PQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9574 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9575 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9576 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9577 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9578 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9579 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9580 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9581 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9582 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9583 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9584 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9585 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9586 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9587 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/");
9588 /* clang-format on */
9589 int i;
9590 const int max_alloc_count = 25;
9591
9592 for (i = 0; i < max_alloc_count; i++) {
9593 allocation_count = i;
9594 XML_SetUserData(g_parser, entity_text);
9595 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9596 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9597 if (XML_SetBase(g_parser, base) == XML_STATUS_ERROR) {
9598 XML_ParserReset(g_parser, NULL);
9599 continue;
9600 }
9601 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9602 != XML_STATUS_ERROR)
9603 break;
9604 /* See comment in test_alloc_parse_xdecl() */
9605 alloc_teardown();
9606 alloc_setup();
9607 }
9608 if (i == 0)
9609 fail("Parsing worked despite failing allocations");
9610 else if (i == max_alloc_count)
9611 fail("Parsing failed even at max allocation count");
9612 }
9613 END_TEST
9614
START_TEST(test_alloc_long_public_id)9615 START_TEST(test_alloc_long_public_id) {
9616 const char *text
9617 = "<!DOCTYPE doc [\n"
9618 " <!ENTITY e PUBLIC '"
9619 /* 64 characters per line */
9620 "LongPublicIDThatShouldResultInAnInternalStringPoolGrowingAtASpec"
9621 "ificMomentKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9622 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9623 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9624 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9625 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9626 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9627 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9628 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9629 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9630 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9631 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9632 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9633 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9634 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9635 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9636 "' 'bar'>\n"
9637 "]>\n"
9638 "<doc>&e;</doc>";
9639 char entity_text[] = "Hello world";
9640 int i;
9641 const int max_alloc_count = 40;
9642
9643 for (i = 0; i < max_alloc_count; i++) {
9644 allocation_count = i;
9645 XML_SetUserData(g_parser, entity_text);
9646 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9647 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9648 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9649 != XML_STATUS_ERROR)
9650 break;
9651 /* See comment in test_alloc_parse_xdecl() */
9652 alloc_teardown();
9653 alloc_setup();
9654 }
9655 if (i == 0)
9656 fail("Parsing worked despite failing allocations");
9657 else if (i == max_alloc_count)
9658 fail("Parsing failed even at max allocation count");
9659 }
9660 END_TEST
9661
START_TEST(test_alloc_long_entity_value)9662 START_TEST(test_alloc_long_entity_value) {
9663 const char *text
9664 = "<!DOCTYPE doc [\n"
9665 " <!ENTITY e1 '"
9666 /* 64 characters per line */
9667 "Long entity value that should provoke a string pool to grow whil"
9668 "e setting up to parse the external entity below. xyz0123456789AB"
9669 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9670 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9671 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9672 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9673 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9674 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9675 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9676 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9677 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9678 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9679 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9680 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9681 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9682 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9683 "'>\n"
9684 " <!ENTITY e2 SYSTEM 'bar'>\n"
9685 "]>\n"
9686 "<doc>&e2;</doc>";
9687 char entity_text[] = "Hello world";
9688 int i;
9689 const int max_alloc_count = 40;
9690
9691 for (i = 0; i < max_alloc_count; i++) {
9692 allocation_count = i;
9693 XML_SetUserData(g_parser, entity_text);
9694 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9695 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9696 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9697 != XML_STATUS_ERROR)
9698 break;
9699 /* See comment in test_alloc_parse_xdecl() */
9700 alloc_teardown();
9701 alloc_setup();
9702 }
9703 if (i == 0)
9704 fail("Parsing worked despite failing allocations");
9705 else if (i == max_alloc_count)
9706 fail("Parsing failed even at max allocation count");
9707 }
9708 END_TEST
9709
START_TEST(test_alloc_long_notation)9710 START_TEST(test_alloc_long_notation) {
9711 const char *text
9712 = "<!DOCTYPE doc [\n"
9713 " <!NOTATION note SYSTEM '"
9714 /* 64 characters per line */
9715 "ALongNotationNameThatShouldProvokeStringPoolGrowthWhileCallingAn"
9716 "ExternalEntityParserUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9717 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9718 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9719 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9720 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9721 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9722 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9723 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9724 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9725 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9726 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9727 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9728 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9729 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9730 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9731 "'>\n"
9732 " <!ENTITY e1 SYSTEM 'foo' NDATA "
9733 /* 64 characters per line */
9734 "ALongNotationNameThatShouldProvokeStringPoolGrowthWhileCallingAn"
9735 "ExternalEntityParserUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9736 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9737 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9738 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9739 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9740 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9741 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9742 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9743 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9744 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9745 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9746 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9747 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9748 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9749 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9750 ">\n"
9751 " <!ENTITY e2 SYSTEM 'bar'>\n"
9752 "]>\n"
9753 "<doc>&e2;</doc>";
9754 ExtOption options[]
9755 = {{XCS("foo"), "Entity Foo"}, {XCS("bar"), "Entity Bar"}, {NULL, NULL}};
9756 int i;
9757 const int max_alloc_count = 40;
9758
9759 for (i = 0; i < max_alloc_count; i++) {
9760 allocation_count = i;
9761 XML_SetUserData(g_parser, options);
9762 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9763 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
9764 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9765 != XML_STATUS_ERROR)
9766 break;
9767
9768 /* See comment in test_alloc_parse_xdecl() */
9769 alloc_teardown();
9770 alloc_setup();
9771 }
9772 if (i == 0)
9773 fail("Parsing worked despite failing allocations");
9774 else if (i == max_alloc_count)
9775 fail("Parsing failed even at max allocation count");
9776 }
9777 END_TEST
9778
9779 static void
nsalloc_setup(void)9780 nsalloc_setup(void) {
9781 XML_Memory_Handling_Suite memsuite = {duff_allocator, duff_reallocator, free};
9782 XML_Char ns_sep[2] = {' ', '\0'};
9783
9784 /* Ensure the parser creation will go through */
9785 allocation_count = ALLOC_ALWAYS_SUCCEED;
9786 reallocation_count = REALLOC_ALWAYS_SUCCEED;
9787 g_parser = XML_ParserCreate_MM(NULL, &memsuite, ns_sep);
9788 if (g_parser == NULL)
9789 fail("Parser not created");
9790 }
9791
9792 static void
nsalloc_teardown(void)9793 nsalloc_teardown(void) {
9794 basic_teardown();
9795 }
9796
9797 /* Test the effects of allocation failure in simple namespace parsing.
9798 * Based on test_ns_default_with_empty_uri()
9799 */
START_TEST(test_nsalloc_xmlns)9800 START_TEST(test_nsalloc_xmlns) {
9801 const char *text = "<doc xmlns='http://example.org/'>\n"
9802 " <e xmlns=''/>\n"
9803 "</doc>";
9804 unsigned int i;
9805 const unsigned int max_alloc_count = 30;
9806
9807 for (i = 0; i < max_alloc_count; i++) {
9808 allocation_count = i;
9809 /* Exercise more code paths with a default handler */
9810 XML_SetDefaultHandler(g_parser, dummy_default_handler);
9811 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9812 != XML_STATUS_ERROR)
9813 break;
9814 /* Resetting the parser is insufficient, because some memory
9815 * allocations are cached within the parser. Instead we use
9816 * the teardown and setup routines to ensure that we have the
9817 * right sort of parser back in our hands.
9818 */
9819 nsalloc_teardown();
9820 nsalloc_setup();
9821 }
9822 if (i == 0)
9823 fail("Parsing worked despite failing allocations");
9824 else if (i == max_alloc_count)
9825 fail("Parsing failed even at maximum allocation count");
9826 }
9827 END_TEST
9828
9829 /* Test XML_ParseBuffer interface with namespace and a dicky allocator */
START_TEST(test_nsalloc_parse_buffer)9830 START_TEST(test_nsalloc_parse_buffer) {
9831 const char *text = "<doc>Hello</doc>";
9832 void *buffer;
9833
9834 /* Try a parse before the start of the world */
9835 /* (Exercises new code path) */
9836 if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_ERROR)
9837 fail("Pre-init XML_ParseBuffer not faulted");
9838 if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_BUFFER)
9839 fail("Pre-init XML_ParseBuffer faulted for wrong reason");
9840
9841 buffer = XML_GetBuffer(g_parser, 1 /* any small number greater than 0 */);
9842 if (buffer == NULL)
9843 fail("Could not acquire parse buffer");
9844
9845 allocation_count = 0;
9846 if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_ERROR)
9847 fail("Pre-init XML_ParseBuffer not faulted");
9848 if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_MEMORY)
9849 fail("Pre-init XML_ParseBuffer faulted for wrong reason");
9850
9851 /* Now with actual memory allocation */
9852 allocation_count = ALLOC_ALWAYS_SUCCEED;
9853 if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_OK)
9854 xml_failure(g_parser);
9855
9856 /* Check that resuming an unsuspended parser is faulted */
9857 if (XML_ResumeParser(g_parser) != XML_STATUS_ERROR)
9858 fail("Resuming unsuspended parser not faulted");
9859 if (XML_GetErrorCode(g_parser) != XML_ERROR_NOT_SUSPENDED)
9860 xml_failure(g_parser);
9861
9862 /* Get the parser into suspended state */
9863 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
9864 resumable = XML_TRUE;
9865 buffer = XML_GetBuffer(g_parser, (int)strlen(text));
9866 if (buffer == NULL)
9867 fail("Could not acquire parse buffer");
9868 assert(buffer != NULL);
9869 memcpy(buffer, text, strlen(text));
9870 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE)
9871 != XML_STATUS_SUSPENDED)
9872 xml_failure(g_parser);
9873 if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE)
9874 xml_failure(g_parser);
9875 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE)
9876 != XML_STATUS_ERROR)
9877 fail("Suspended XML_ParseBuffer not faulted");
9878 if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED)
9879 xml_failure(g_parser);
9880 if (XML_GetBuffer(g_parser, (int)strlen(text)) != NULL)
9881 fail("Suspended XML_GetBuffer not faulted");
9882
9883 /* Get it going again and complete the world */
9884 XML_SetCharacterDataHandler(g_parser, NULL);
9885 if (XML_ResumeParser(g_parser) != XML_STATUS_OK)
9886 xml_failure(g_parser);
9887 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE)
9888 != XML_STATUS_ERROR)
9889 fail("Post-finishing XML_ParseBuffer not faulted");
9890 if (XML_GetErrorCode(g_parser) != XML_ERROR_FINISHED)
9891 xml_failure(g_parser);
9892 if (XML_GetBuffer(g_parser, (int)strlen(text)) != NULL)
9893 fail("Post-finishing XML_GetBuffer not faulted");
9894 }
9895 END_TEST
9896
9897 /* Check handling of long prefix names (pool growth) */
START_TEST(test_nsalloc_long_prefix)9898 START_TEST(test_nsalloc_long_prefix) {
9899 const char *text
9900 = "<"
9901 /* 64 characters per line */
9902 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9903 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9904 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9905 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9906 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9907 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9908 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9909 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9910 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9911 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9912 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9913 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9914 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9915 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9916 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9917 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9918 ":foo xmlns:"
9919 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9920 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9921 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9922 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9923 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9924 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9925 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9926 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9927 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9928 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9929 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9930 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9931 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9932 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9933 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9934 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9935 "='http://example.org/'>"
9936 "</"
9937 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9938 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9939 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9940 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9941 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9942 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9943 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9944 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9945 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9946 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9947 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9948 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9949 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9950 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9951 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9952 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9953 ":foo>";
9954 int i;
9955 const int max_alloc_count = 40;
9956
9957 for (i = 0; i < max_alloc_count; i++) {
9958 allocation_count = i;
9959 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9960 != XML_STATUS_ERROR)
9961 break;
9962 /* See comment in test_nsalloc_xmlns() */
9963 nsalloc_teardown();
9964 nsalloc_setup();
9965 }
9966 if (i == 0)
9967 fail("Parsing worked despite failing allocations");
9968 else if (i == max_alloc_count)
9969 fail("Parsing failed even at max allocation count");
9970 }
9971 END_TEST
9972
9973 /* Check handling of long uri names (pool growth) */
START_TEST(test_nsalloc_long_uri)9974 START_TEST(test_nsalloc_long_uri) {
9975 const char *text
9976 = "<foo:e xmlns:foo='http://example.org/"
9977 /* 64 characters per line */
9978 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9979 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9980 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9981 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9982 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9983 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9984 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9985 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9986 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9987 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9988 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9989 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9990 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9991 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9992 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9993 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9994 "' bar:a='12'\n"
9995 "xmlns:bar='http://example.org/"
9996 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9997 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9998 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9999 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10000 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10001 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10002 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10003 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10004 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10005 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10006 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10007 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10008 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10009 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10010 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10011 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10012 "'>"
10013 "</foo:e>";
10014 int i;
10015 const int max_alloc_count = 40;
10016
10017 for (i = 0; i < max_alloc_count; i++) {
10018 allocation_count = i;
10019 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10020 != XML_STATUS_ERROR)
10021 break;
10022 /* See comment in test_nsalloc_xmlns() */
10023 nsalloc_teardown();
10024 nsalloc_setup();
10025 }
10026 if (i == 0)
10027 fail("Parsing worked despite failing allocations");
10028 else if (i == max_alloc_count)
10029 fail("Parsing failed even at max allocation count");
10030 }
10031 END_TEST
10032
10033 /* Test handling of long attribute names with prefixes */
START_TEST(test_nsalloc_long_attr)10034 START_TEST(test_nsalloc_long_attr) {
10035 const char *text
10036 = "<foo:e xmlns:foo='http://example.org/' bar:"
10037 /* 64 characters per line */
10038 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10039 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10040 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10041 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10042 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10043 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10044 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10045 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10046 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10047 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10048 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10049 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10050 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10051 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10052 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10053 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10054 "='12'\n"
10055 "xmlns:bar='http://example.org/'>"
10056 "</foo:e>";
10057 int i;
10058 const int max_alloc_count = 40;
10059
10060 for (i = 0; i < max_alloc_count; i++) {
10061 allocation_count = i;
10062 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10063 != XML_STATUS_ERROR)
10064 break;
10065 /* See comment in test_nsalloc_xmlns() */
10066 nsalloc_teardown();
10067 nsalloc_setup();
10068 }
10069 if (i == 0)
10070 fail("Parsing worked despite failing allocations");
10071 else if (i == max_alloc_count)
10072 fail("Parsing failed even at max allocation count");
10073 }
10074 END_TEST
10075
10076 /* Test handling of an attribute name with a long namespace prefix */
START_TEST(test_nsalloc_long_attr_prefix)10077 START_TEST(test_nsalloc_long_attr_prefix) {
10078 const char *text
10079 = "<foo:e xmlns:foo='http://example.org/' "
10080 /* 64 characters per line */
10081 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10082 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10083 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10084 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10085 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10086 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10087 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10088 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10089 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10090 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10091 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10092 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10093 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10094 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10095 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10096 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10097 ":a='12'\n"
10098 "xmlns:"
10099 /* 64 characters per line */
10100 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10101 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10102 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10103 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10104 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10105 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10106 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10107 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10108 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10109 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10110 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10111 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10112 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10113 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10114 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10115 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10116 "='http://example.org/'>"
10117 "</foo:e>";
10118 const XML_Char *elemstr[] = {
10119 /* clang-format off */
10120 XCS("http://example.org/ e foo"),
10121 XCS("http://example.org/ a ")
10122 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10123 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10124 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10125 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10126 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10127 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10128 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10129 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10130 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10131 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10132 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10133 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10134 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10135 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10136 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10137 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10138 /* clang-format on */
10139 };
10140 int i;
10141 const int max_alloc_count = 40;
10142
10143 for (i = 0; i < max_alloc_count; i++) {
10144 allocation_count = i;
10145 XML_SetReturnNSTriplet(g_parser, XML_TRUE);
10146 XML_SetUserData(g_parser, (void *)elemstr);
10147 XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
10148 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10149 != XML_STATUS_ERROR)
10150 break;
10151 /* See comment in test_nsalloc_xmlns() */
10152 nsalloc_teardown();
10153 nsalloc_setup();
10154 }
10155 if (i == 0)
10156 fail("Parsing worked despite failing allocations");
10157 else if (i == max_alloc_count)
10158 fail("Parsing failed even at max allocation count");
10159 }
10160 END_TEST
10161
10162 /* Test attribute handling in the face of a dodgy reallocator */
START_TEST(test_nsalloc_realloc_attributes)10163 START_TEST(test_nsalloc_realloc_attributes) {
10164 const char *text = "<foo:e xmlns:foo='http://example.org/' bar:a='12'\n"
10165 " xmlns:bar='http://example.org/'>"
10166 "</foo:e>";
10167 int i;
10168 const int max_realloc_count = 10;
10169
10170 for (i = 0; i < max_realloc_count; i++) {
10171 reallocation_count = i;
10172 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10173 != XML_STATUS_ERROR)
10174 break;
10175 /* See comment in test_nsalloc_xmlns() */
10176 nsalloc_teardown();
10177 nsalloc_setup();
10178 }
10179 if (i == 0)
10180 fail("Parsing worked despite failing reallocations");
10181 else if (i == max_realloc_count)
10182 fail("Parsing failed at max reallocation count");
10183 }
10184 END_TEST
10185
10186 /* Test long element names with namespaces under a failing allocator */
START_TEST(test_nsalloc_long_element)10187 START_TEST(test_nsalloc_long_element) {
10188 const char *text
10189 = "<foo:thisisalongenoughelementnametotriggerareallocation\n"
10190 " xmlns:foo='http://example.org/' bar:a='12'\n"
10191 " xmlns:bar='http://example.org/'>"
10192 "</foo:thisisalongenoughelementnametotriggerareallocation>";
10193 const XML_Char *elemstr[]
10194 = {XCS("http://example.org/")
10195 XCS(" thisisalongenoughelementnametotriggerareallocation foo"),
10196 XCS("http://example.org/ a bar")};
10197 int i;
10198 const int max_alloc_count = 30;
10199
10200 for (i = 0; i < max_alloc_count; i++) {
10201 allocation_count = i;
10202 XML_SetReturnNSTriplet(g_parser, XML_TRUE);
10203 XML_SetUserData(g_parser, (void *)elemstr);
10204 XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
10205 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10206 != XML_STATUS_ERROR)
10207 break;
10208 /* See comment in test_nsalloc_xmlns() */
10209 nsalloc_teardown();
10210 nsalloc_setup();
10211 }
10212 if (i == 0)
10213 fail("Parsing worked despite failing reallocations");
10214 else if (i == max_alloc_count)
10215 fail("Parsing failed at max reallocation count");
10216 }
10217 END_TEST
10218
10219 /* Test the effects of reallocation failure when reassigning a
10220 * binding.
10221 *
10222 * XML_ParserReset does not free the BINDING structures used by a
10223 * parser, but instead adds them to an internal free list to be reused
10224 * as necessary. Likewise the URI buffers allocated for the binding
10225 * aren't freed, but kept attached to their existing binding. If the
10226 * new binding has a longer URI, it will need reallocation. This test
10227 * provokes that reallocation, and tests the control path if it fails.
10228 */
START_TEST(test_nsalloc_realloc_binding_uri)10229 START_TEST(test_nsalloc_realloc_binding_uri) {
10230 const char *first = "<doc xmlns='http://example.org/'>\n"
10231 " <e xmlns='' />\n"
10232 "</doc>";
10233 const char *second
10234 = "<doc xmlns='http://example.org/long/enough/URI/to/reallocate/'>\n"
10235 " <e xmlns='' />\n"
10236 "</doc>";
10237 unsigned i;
10238 const unsigned max_realloc_count = 10;
10239
10240 /* First, do a full parse that will leave bindings around */
10241 if (_XML_Parse_SINGLE_BYTES(g_parser, first, (int)strlen(first), XML_TRUE)
10242 == XML_STATUS_ERROR)
10243 xml_failure(g_parser);
10244
10245 /* Now repeat with a longer URI and a duff reallocator */
10246 for (i = 0; i < max_realloc_count; i++) {
10247 XML_ParserReset(g_parser, NULL);
10248 reallocation_count = i;
10249 if (_XML_Parse_SINGLE_BYTES(g_parser, second, (int)strlen(second), XML_TRUE)
10250 != XML_STATUS_ERROR)
10251 break;
10252 }
10253 if (i == 0)
10254 fail("Parsing worked despite failing reallocation");
10255 else if (i == max_realloc_count)
10256 fail("Parsing failed at max reallocation count");
10257 }
10258 END_TEST
10259
10260 /* Check handling of long prefix names (pool growth) */
START_TEST(test_nsalloc_realloc_long_prefix)10261 START_TEST(test_nsalloc_realloc_long_prefix) {
10262 const char *text
10263 = "<"
10264 /* 64 characters per line */
10265 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10266 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10267 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10268 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10269 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10270 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10271 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10272 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10273 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10274 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10275 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10276 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10277 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10278 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10279 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10280 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10281 ":foo xmlns:"
10282 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10283 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10284 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10285 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10286 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10287 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10288 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10289 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10290 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10291 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10292 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10293 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10294 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10295 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10296 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10297 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10298 "='http://example.org/'>"
10299 "</"
10300 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10301 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10302 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10303 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10304 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10305 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10306 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10307 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10308 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10309 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10310 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10311 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10312 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10313 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10314 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10315 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10316 ":foo>";
10317 int i;
10318 const int max_realloc_count = 12;
10319
10320 for (i = 0; i < max_realloc_count; i++) {
10321 reallocation_count = i;
10322 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10323 != XML_STATUS_ERROR)
10324 break;
10325 /* See comment in test_nsalloc_xmlns() */
10326 nsalloc_teardown();
10327 nsalloc_setup();
10328 }
10329 if (i == 0)
10330 fail("Parsing worked despite failing reallocations");
10331 else if (i == max_realloc_count)
10332 fail("Parsing failed even at max reallocation count");
10333 }
10334 END_TEST
10335
10336 /* Check handling of even long prefix names (different code path) */
START_TEST(test_nsalloc_realloc_longer_prefix)10337 START_TEST(test_nsalloc_realloc_longer_prefix) {
10338 const char *text
10339 = "<"
10340 /* 64 characters per line */
10341 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10342 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10343 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10344 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10345 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10346 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10347 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10348 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10349 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10350 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10351 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10352 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10353 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10354 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10355 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10356 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10357 "Q:foo xmlns:"
10358 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10359 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10360 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10361 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10362 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10363 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10364 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10365 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10366 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10367 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10368 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10369 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10370 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10371 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10372 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10373 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10374 "Q='http://example.org/'>"
10375 "</"
10376 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10377 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10378 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10379 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10380 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10381 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10382 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10383 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10384 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10385 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10386 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10387 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10388 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10389 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10390 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10391 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10392 "Q:foo>";
10393 int i;
10394 const int max_realloc_count = 12;
10395
10396 for (i = 0; i < max_realloc_count; i++) {
10397 reallocation_count = i;
10398 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10399 != XML_STATUS_ERROR)
10400 break;
10401 /* See comment in test_nsalloc_xmlns() */
10402 nsalloc_teardown();
10403 nsalloc_setup();
10404 }
10405 if (i == 0)
10406 fail("Parsing worked despite failing reallocations");
10407 else if (i == max_realloc_count)
10408 fail("Parsing failed even at max reallocation count");
10409 }
10410 END_TEST
10411
START_TEST(test_nsalloc_long_namespace)10412 START_TEST(test_nsalloc_long_namespace) {
10413 const char *text1
10414 = "<"
10415 /* 64 characters per line */
10416 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10417 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10418 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10419 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10420 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10421 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10422 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10423 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10424 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10425 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10426 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10427 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10428 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10429 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10430 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10431 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10432 ":e xmlns:"
10433 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10434 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10435 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10436 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10437 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10438 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10439 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10440 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10441 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10442 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10443 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10444 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10445 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10446 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10447 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10448 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10449 "='http://example.org/'>\n";
10450 const char *text2
10451 = "<"
10452 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10453 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10454 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10455 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10456 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10457 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10458 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10459 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10460 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10461 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10462 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10463 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10464 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10465 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10466 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10467 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10468 ":f "
10469 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10470 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10471 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10472 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10473 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10474 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10475 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10476 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10477 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10478 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10479 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10480 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10481 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10482 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10483 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10484 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10485 ":attr='foo'/>\n"
10486 "</"
10487 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10488 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10489 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10490 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10491 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10492 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10493 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10494 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10495 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10496 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10497 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10498 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10499 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10500 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10501 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10502 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10503 ":e>";
10504 int i;
10505 const int max_alloc_count = 40;
10506
10507 for (i = 0; i < max_alloc_count; i++) {
10508 allocation_count = i;
10509 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
10510 != XML_STATUS_ERROR
10511 && _XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2),
10512 XML_TRUE)
10513 != XML_STATUS_ERROR)
10514 break;
10515 /* See comment in test_nsalloc_xmlns() */
10516 nsalloc_teardown();
10517 nsalloc_setup();
10518 }
10519 if (i == 0)
10520 fail("Parsing worked despite failing allocations");
10521 else if (i == max_alloc_count)
10522 fail("Parsing failed even at max allocation count");
10523 }
10524 END_TEST
10525
10526 /* Using a slightly shorter namespace name provokes allocations in
10527 * slightly different places in the code.
10528 */
START_TEST(test_nsalloc_less_long_namespace)10529 START_TEST(test_nsalloc_less_long_namespace) {
10530 const char *text
10531 = "<"
10532 /* 64 characters per line */
10533 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10534 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10535 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10536 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10537 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10538 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10539 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10540 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10541 ":e xmlns:"
10542 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10543 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10544 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10545 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10546 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10547 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10548 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10549 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10550 "='http://example.org/'>\n"
10551 "<"
10552 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10553 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10554 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10555 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10556 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10557 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10558 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10559 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10560 ":f "
10561 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10562 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10563 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10564 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10565 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10566 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10567 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10568 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10569 ":att='foo'/>\n"
10570 "</"
10571 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10572 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10573 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10574 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10575 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10576 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10577 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10578 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10579 ":e>";
10580 int i;
10581 const int max_alloc_count = 40;
10582
10583 for (i = 0; i < max_alloc_count; i++) {
10584 allocation_count = i;
10585 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10586 != XML_STATUS_ERROR)
10587 break;
10588 /* See comment in test_nsalloc_xmlns() */
10589 nsalloc_teardown();
10590 nsalloc_setup();
10591 }
10592 if (i == 0)
10593 fail("Parsing worked despite failing allocations");
10594 else if (i == max_alloc_count)
10595 fail("Parsing failed even at max allocation count");
10596 }
10597 END_TEST
10598
START_TEST(test_nsalloc_long_context)10599 START_TEST(test_nsalloc_long_context) {
10600 const char *text
10601 = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10602 " <!ATTLIST doc baz ID #REQUIRED>\n"
10603 " <!ENTITY en SYSTEM 'bar'>\n"
10604 "]>\n"
10605 "<doc xmlns='http://example.org/"
10606 /* 64 characters per line */
10607 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10608 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10609 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10610 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10611 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10612 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10613 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10614 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10615 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10616 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10617 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10618 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10619 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10620 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10621 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10622 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKL"
10623 "' baz='2'>\n"
10624 "&en;"
10625 "</doc>";
10626 ExtOption options[] = {
10627 {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}};
10628 int i;
10629 const int max_alloc_count = 70;
10630
10631 for (i = 0; i < max_alloc_count; i++) {
10632 allocation_count = i;
10633 XML_SetUserData(g_parser, options);
10634 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
10635 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
10636 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10637 != XML_STATUS_ERROR)
10638 break;
10639
10640 /* See comment in test_nsalloc_xmlns() */
10641 nsalloc_teardown();
10642 nsalloc_setup();
10643 }
10644 if (i == 0)
10645 fail("Parsing worked despite failing allocations");
10646 else if (i == max_alloc_count)
10647 fail("Parsing failed even at max allocation count");
10648 }
10649 END_TEST
10650
10651 /* This function is void; it will throw a fail() on error, so if it
10652 * returns normally it must have succeeded.
10653 */
10654 static void
context_realloc_test(const char * text)10655 context_realloc_test(const char *text) {
10656 ExtOption options[] = {
10657 {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}};
10658 int i;
10659 const int max_realloc_count = 6;
10660
10661 for (i = 0; i < max_realloc_count; i++) {
10662 reallocation_count = i;
10663 XML_SetUserData(g_parser, options);
10664 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
10665 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
10666 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10667 != XML_STATUS_ERROR)
10668 break;
10669 /* See comment in test_nsalloc_xmlns() */
10670 nsalloc_teardown();
10671 nsalloc_setup();
10672 }
10673 if (i == 0)
10674 fail("Parsing worked despite failing reallocations");
10675 else if (i == max_realloc_count)
10676 fail("Parsing failed even at max reallocation count");
10677 }
10678
START_TEST(test_nsalloc_realloc_long_context)10679 START_TEST(test_nsalloc_realloc_long_context) {
10680 const char *text
10681 = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10682 " <!ENTITY en SYSTEM 'bar'>\n"
10683 "]>\n"
10684 "<doc xmlns='http://example.org/"
10685 /* 64 characters per line */
10686 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10687 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10688 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10689 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10690 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10691 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
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/ABCDEFGHIJKL"
10702 "'>\n"
10703 "&en;"
10704 "</doc>";
10705
10706 context_realloc_test(text);
10707 }
10708 END_TEST
10709
START_TEST(test_nsalloc_realloc_long_context_2)10710 START_TEST(test_nsalloc_realloc_long_context_2) {
10711 const char *text
10712 = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10713 " <!ENTITY en SYSTEM 'bar'>\n"
10714 "]>\n"
10715 "<doc xmlns='http://example.org/"
10716 /* 64 characters per line */
10717 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10718 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10719 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10720 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10721 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10722 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
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/ABCDEFGHIJK"
10733 "'>\n"
10734 "&en;"
10735 "</doc>";
10736
10737 context_realloc_test(text);
10738 }
10739 END_TEST
10740
START_TEST(test_nsalloc_realloc_long_context_3)10741 START_TEST(test_nsalloc_realloc_long_context_3) {
10742 const char *text
10743 = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10744 " <!ENTITY en SYSTEM 'bar'>\n"
10745 "]>\n"
10746 "<doc xmlns='http://example.org/"
10747 /* 64 characters per line */
10748 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10749 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10750 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10751 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10752 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10753 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
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/ABCDEFGH"
10764 "'>\n"
10765 "&en;"
10766 "</doc>";
10767
10768 context_realloc_test(text);
10769 }
10770 END_TEST
10771
START_TEST(test_nsalloc_realloc_long_context_4)10772 START_TEST(test_nsalloc_realloc_long_context_4) {
10773 const char *text
10774 = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10775 " <!ENTITY en SYSTEM 'bar'>\n"
10776 "]>\n"
10777 "<doc xmlns='http://example.org/"
10778 /* 64 characters per line */
10779 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10780 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10781 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10782 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10783 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10784 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
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"
10795 "'>\n"
10796 "&en;"
10797 "</doc>";
10798
10799 context_realloc_test(text);
10800 }
10801 END_TEST
10802
START_TEST(test_nsalloc_realloc_long_context_5)10803 START_TEST(test_nsalloc_realloc_long_context_5) {
10804 const char *text
10805 = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10806 " <!ENTITY en SYSTEM 'bar'>\n"
10807 "]>\n"
10808 "<doc xmlns='http://example.org/"
10809 /* 64 characters per line */
10810 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10811 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10812 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10813 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10814 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10815 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
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 "ABC"
10826 "'>\n"
10827 "&en;"
10828 "</doc>";
10829
10830 context_realloc_test(text);
10831 }
10832 END_TEST
10833
START_TEST(test_nsalloc_realloc_long_context_6)10834 START_TEST(test_nsalloc_realloc_long_context_6) {
10835 const char *text
10836 = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10837 " <!ENTITY en SYSTEM 'bar'>\n"
10838 "]>\n"
10839 "<doc xmlns='http://example.org/"
10840 /* 64 characters per line */
10841 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10842 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10843 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10844 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10845 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
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/ABCDEFGHIJKLMNOP"
10856 "'>\n"
10857 "&en;"
10858 "</doc>";
10859
10860 context_realloc_test(text);
10861 }
10862 END_TEST
10863
START_TEST(test_nsalloc_realloc_long_context_7)10864 START_TEST(test_nsalloc_realloc_long_context_7) {
10865 const char *text
10866 = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10867 " <!ENTITY en SYSTEM 'bar'>\n"
10868 "]>\n"
10869 "<doc xmlns='http://example.org/"
10870 /* 64 characters per line */
10871 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10872 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10873 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10874 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10875 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10876 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10877 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10878 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10879 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10880 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10881 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10882 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10883 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10884 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10885 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10886 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLM"
10887 "'>\n"
10888 "&en;"
10889 "</doc>";
10890
10891 context_realloc_test(text);
10892 }
10893 END_TEST
10894
START_TEST(test_nsalloc_realloc_long_ge_name)10895 START_TEST(test_nsalloc_realloc_long_ge_name) {
10896 const char *text
10897 = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10898 " <!ENTITY "
10899 /* 64 characters per line */
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 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10913 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10914 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10915 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10916 " SYSTEM 'bar'>\n"
10917 "]>\n"
10918 "<doc xmlns='http://example.org/baz'>\n"
10919 "&"
10920 /* 64 characters per line */
10921 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10922 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10923 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10924 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10925 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10926 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10927 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10928 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10929 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10930 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10931 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10932 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10933 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10934 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10935 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10936 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10937 ";"
10938 "</doc>";
10939 ExtOption options[] = {
10940 {XCS("foo"), "<!ELEMENT el EMPTY>"}, {XCS("bar"), "<el/>"}, {NULL, NULL}};
10941 int i;
10942 const int max_realloc_count = 10;
10943
10944 for (i = 0; i < max_realloc_count; i++) {
10945 reallocation_count = i;
10946 XML_SetUserData(g_parser, options);
10947 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
10948 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
10949 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10950 != XML_STATUS_ERROR)
10951 break;
10952 /* See comment in test_nsalloc_xmlns() */
10953 nsalloc_teardown();
10954 nsalloc_setup();
10955 }
10956 if (i == 0)
10957 fail("Parsing worked despite failing reallocations");
10958 else if (i == max_realloc_count)
10959 fail("Parsing failed even at max reallocation count");
10960 }
10961 END_TEST
10962
10963 /* Test that when a namespace is passed through the context mechanism
10964 * to an external entity parser, the parsers handle reallocation
10965 * failures correctly. The prefix is exactly the right length to
10966 * provoke particular uncommon code paths.
10967 */
START_TEST(test_nsalloc_realloc_long_context_in_dtd)10968 START_TEST(test_nsalloc_realloc_long_context_in_dtd) {
10969 const char *text1
10970 = "<!DOCTYPE "
10971 /* 64 characters per line */
10972 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10973 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10974 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10975 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10976 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10977 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10978 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10979 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10980 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10981 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10982 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10983 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10984 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10985 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10986 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10987 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10988 ":doc [\n"
10989 " <!ENTITY First SYSTEM 'foo/First'>\n"
10990 "]>\n"
10991 "<"
10992 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10993 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10994 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10995 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10996 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10997 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10998 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10999 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11000 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11001 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11002 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11003 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11004 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11005 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11006 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11007 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11008 ":doc xmlns:"
11009 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11010 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11011 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11012 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11013 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11014 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11015 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11016 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11017 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11018 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11019 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11020 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11021 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11022 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11023 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11024 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11025 "='foo/Second'>&First;";
11026 const char *text2
11027 = "</"
11028 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11029 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11030 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11031 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11032 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11033 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11034 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11035 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11036 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11037 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11038 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11039 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11040 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11041 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11042 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11043 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11044 ":doc>";
11045 ExtOption options[] = {{XCS("foo/First"), "Hello world"}, {NULL, NULL}};
11046 int i;
11047 const int max_realloc_count = 20;
11048
11049 for (i = 0; i < max_realloc_count; i++) {
11050 reallocation_count = i;
11051 XML_SetUserData(g_parser, options);
11052 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11053 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11054 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
11055 != XML_STATUS_ERROR
11056 && _XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2),
11057 XML_TRUE)
11058 != XML_STATUS_ERROR)
11059 break;
11060 /* See comment in test_nsalloc_xmlns() */
11061 nsalloc_teardown();
11062 nsalloc_setup();
11063 }
11064 if (i == 0)
11065 fail("Parsing worked despite failing reallocations");
11066 else if (i == max_realloc_count)
11067 fail("Parsing failed even at max reallocation count");
11068 }
11069 END_TEST
11070
START_TEST(test_nsalloc_long_default_in_ext)11071 START_TEST(test_nsalloc_long_default_in_ext) {
11072 const char *text
11073 = "<!DOCTYPE doc [\n"
11074 " <!ATTLIST e a1 CDATA '"
11075 /* 64 characters per line */
11076 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11077 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11078 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11079 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11080 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11081 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11082 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11083 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11084 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11085 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11086 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11087 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11088 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11089 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11090 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11091 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11092 "'>\n"
11093 " <!ENTITY x SYSTEM 'foo'>\n"
11094 "]>\n"
11095 "<doc>&x;</doc>";
11096 ExtOption options[] = {{XCS("foo"), "<e/>"}, {NULL, NULL}};
11097 int i;
11098 const int max_alloc_count = 50;
11099
11100 for (i = 0; i < max_alloc_count; i++) {
11101 allocation_count = i;
11102 XML_SetUserData(g_parser, options);
11103 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11104 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11105 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
11106 != XML_STATUS_ERROR)
11107 break;
11108
11109 /* See comment in test_nsalloc_xmlns() */
11110 nsalloc_teardown();
11111 nsalloc_setup();
11112 }
11113 if (i == 0)
11114 fail("Parsing worked despite failing allocations");
11115 else if (i == max_alloc_count)
11116 fail("Parsing failed even at max allocation count");
11117 }
11118 END_TEST
11119
START_TEST(test_nsalloc_long_systemid_in_ext)11120 START_TEST(test_nsalloc_long_systemid_in_ext) {
11121 const char *text
11122 = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11123 " <!ENTITY en SYSTEM '"
11124 /* 64 characters per line */
11125 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11126 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11127 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11128 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11129 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11130 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11131 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11132 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11133 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11134 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11135 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11136 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11137 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11138 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11139 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11140 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11141 "'>\n"
11142 "]>\n"
11143 "<doc>&en;</doc>";
11144 ExtOption options[] = {
11145 {XCS("foo"), "<!ELEMENT e EMPTY>"},
11146 {/* clang-format off */
11147 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11148 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11149 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11150 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11151 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11152 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11153 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11154 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11155 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11156 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11157 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11158 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11159 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11160 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11161 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11162 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"),
11163 /* clang-format on */
11164 "<e/>"},
11165 {NULL, NULL}};
11166 int i;
11167 const int max_alloc_count = 55;
11168
11169 for (i = 0; i < max_alloc_count; i++) {
11170 allocation_count = i;
11171 XML_SetUserData(g_parser, options);
11172 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11173 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11174 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
11175 != XML_STATUS_ERROR)
11176 break;
11177
11178 /* See comment in test_nsalloc_xmlns() */
11179 nsalloc_teardown();
11180 nsalloc_setup();
11181 }
11182 if (i == 0)
11183 fail("Parsing worked despite failing allocations");
11184 else if (i == max_alloc_count)
11185 fail("Parsing failed even at max allocation count");
11186 }
11187 END_TEST
11188
11189 /* Test the effects of allocation failure on parsing an element in a
11190 * namespace. Based on test_nsalloc_long_context.
11191 */
START_TEST(test_nsalloc_prefixed_element)11192 START_TEST(test_nsalloc_prefixed_element) {
11193 const char *text = "<!DOCTYPE pfx:element SYSTEM 'foo' [\n"
11194 " <!ATTLIST pfx:element baz ID #REQUIRED>\n"
11195 " <!ENTITY en SYSTEM 'bar'>\n"
11196 "]>\n"
11197 "<pfx:element xmlns:pfx='http://example.org/' baz='2'>\n"
11198 "&en;"
11199 "</pfx:element>";
11200 ExtOption options[] = {
11201 {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}};
11202 int i;
11203 const int max_alloc_count = 70;
11204
11205 for (i = 0; i < max_alloc_count; i++) {
11206 allocation_count = i;
11207 XML_SetUserData(g_parser, options);
11208 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11209 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11210 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
11211 != XML_STATUS_ERROR)
11212 break;
11213
11214 /* See comment in test_nsalloc_xmlns() */
11215 nsalloc_teardown();
11216 nsalloc_setup();
11217 }
11218 if (i == 0)
11219 fail("Success despite failing allocator");
11220 else if (i == max_alloc_count)
11221 fail("Failed even at full allocation count");
11222 }
11223 END_TEST
11224
11225 static Suite *
make_suite(void)11226 make_suite(void) {
11227 Suite *s = suite_create("basic");
11228 TCase *tc_basic = tcase_create("basic tests");
11229 TCase *tc_namespace = tcase_create("XML namespaces");
11230 TCase *tc_misc = tcase_create("miscellaneous tests");
11231 TCase *tc_alloc = tcase_create("allocation tests");
11232 TCase *tc_nsalloc = tcase_create("namespace allocation tests");
11233
11234 suite_add_tcase(s, tc_basic);
11235 tcase_add_checked_fixture(tc_basic, basic_setup, basic_teardown);
11236 tcase_add_test(tc_basic, test_nul_byte);
11237 tcase_add_test(tc_basic, test_u0000_char);
11238 tcase_add_test(tc_basic, test_siphash_self);
11239 tcase_add_test(tc_basic, test_siphash_spec);
11240 tcase_add_test(tc_basic, test_bom_utf8);
11241 tcase_add_test(tc_basic, test_bom_utf16_be);
11242 tcase_add_test(tc_basic, test_bom_utf16_le);
11243 tcase_add_test(tc_basic, test_nobom_utf16_le);
11244 tcase_add_test(tc_basic, test_illegal_utf8);
11245 tcase_add_test(tc_basic, test_utf8_auto_align);
11246 tcase_add_test(tc_basic, test_utf16);
11247 tcase_add_test(tc_basic, test_utf16_le_epilog_newline);
11248 tcase_add_test(tc_basic, test_not_utf16);
11249 tcase_add_test(tc_basic, test_bad_encoding);
11250 tcase_add_test(tc_basic, test_latin1_umlauts);
11251 tcase_add_test(tc_basic, test_long_utf8_character);
11252 tcase_add_test(tc_basic, test_long_latin1_attribute);
11253 tcase_add_test(tc_basic, test_long_ascii_attribute);
11254 /* Regression test for SF bug #491986. */
11255 tcase_add_test(tc_basic, test_danish_latin1);
11256 /* Regression test for SF bug #514281. */
11257 tcase_add_test(tc_basic, test_french_charref_hexidecimal);
11258 tcase_add_test(tc_basic, test_french_charref_decimal);
11259 tcase_add_test(tc_basic, test_french_latin1);
11260 tcase_add_test(tc_basic, test_french_utf8);
11261 tcase_add_test(tc_basic, test_utf8_false_rejection);
11262 tcase_add_test(tc_basic, test_line_number_after_parse);
11263 tcase_add_test(tc_basic, test_column_number_after_parse);
11264 tcase_add_test(tc_basic, test_line_and_column_numbers_inside_handlers);
11265 tcase_add_test(tc_basic, test_line_number_after_error);
11266 tcase_add_test(tc_basic, test_column_number_after_error);
11267 tcase_add_test(tc_basic, test_really_long_lines);
11268 tcase_add_test(tc_basic, test_really_long_encoded_lines);
11269 tcase_add_test(tc_basic, test_end_element_events);
11270 tcase_add_test(tc_basic, test_attr_whitespace_normalization);
11271 tcase_add_test(tc_basic, test_xmldecl_misplaced);
11272 tcase_add_test(tc_basic, test_xmldecl_invalid);
11273 tcase_add_test(tc_basic, test_xmldecl_missing_attr);
11274 tcase_add_test(tc_basic, test_xmldecl_missing_value);
11275 tcase_add_test(tc_basic, test_unknown_encoding_internal_entity);
11276 tcase_add_test(tc_basic, test_unrecognised_encoding_internal_entity);
11277 tcase_add_test(tc_basic, test_wfc_undeclared_entity_unread_external_subset);
11278 tcase_add_test(tc_basic, test_wfc_undeclared_entity_no_external_subset);
11279 tcase_add_test(tc_basic, test_wfc_undeclared_entity_standalone);
11280 tcase_add_test(tc_basic, test_wfc_undeclared_entity_with_external_subset);
11281 tcase_add_test(tc_basic, test_not_standalone_handler_reject);
11282 tcase_add_test(tc_basic, test_not_standalone_handler_accept);
11283 tcase_add_test(tc_basic,
11284 test_wfc_undeclared_entity_with_external_subset_standalone);
11285 tcase_add_test(tc_basic, test_entity_with_external_subset_unless_standalone);
11286 tcase_add_test(tc_basic, test_wfc_no_recursive_entity_refs);
11287 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_set_encoding);
11288 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_no_handler);
11289 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_set_bom);
11290 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_bad_encoding);
11291 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_bad_encoding_2);
11292 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_invalid_parse);
11293 tcase_add_test__ifdef_xml_dtd(tc_basic,
11294 test_ext_entity_invalid_suspended_parse);
11295 tcase_add_test(tc_basic, test_dtd_default_handling);
11296 tcase_add_test(tc_basic, test_dtd_attr_handling);
11297 tcase_add_test(tc_basic, test_empty_ns_without_namespaces);
11298 tcase_add_test(tc_basic, test_ns_in_attribute_default_without_namespaces);
11299 tcase_add_test(tc_basic, test_stop_parser_between_char_data_calls);
11300 tcase_add_test(tc_basic, test_suspend_parser_between_char_data_calls);
11301 tcase_add_test(tc_basic, test_repeated_stop_parser_between_char_data_calls);
11302 tcase_add_test(tc_basic, test_good_cdata_ascii);
11303 tcase_add_test(tc_basic, test_good_cdata_utf16);
11304 tcase_add_test(tc_basic, test_good_cdata_utf16_le);
11305 tcase_add_test(tc_basic, test_long_cdata_utf16);
11306 #ifndef XML_MIN_SIZE /* FIXME workaround -DXML_MIN_SIZE + ASan (issue #332) */
11307 tcase_add_test(tc_basic, test_multichar_cdata_utf16);
11308 #endif
11309 tcase_add_test(tc_basic, test_utf16_bad_surrogate_pair);
11310 tcase_add_test(tc_basic, test_bad_cdata);
11311 #ifndef XML_MIN_SIZE /* FIXME workaround -DXML_MIN_SIZE + ASan (issue #332) */
11312 tcase_add_test(tc_basic, test_bad_cdata_utf16);
11313 #endif
11314 tcase_add_test(tc_basic, test_stop_parser_between_cdata_calls);
11315 tcase_add_test(tc_basic, test_suspend_parser_between_cdata_calls);
11316 tcase_add_test(tc_basic, test_memory_allocation);
11317 tcase_add_test(tc_basic, test_default_current);
11318 tcase_add_test(tc_basic, test_dtd_elements);
11319 tcase_add_test__ifdef_xml_dtd(tc_basic, test_set_foreign_dtd);
11320 tcase_add_test__ifdef_xml_dtd(tc_basic, test_foreign_dtd_not_standalone);
11321 tcase_add_test__ifdef_xml_dtd(tc_basic, test_invalid_foreign_dtd);
11322 tcase_add_test__ifdef_xml_dtd(tc_basic, test_foreign_dtd_with_doctype);
11323 tcase_add_test__ifdef_xml_dtd(tc_basic,
11324 test_foreign_dtd_without_external_subset);
11325 tcase_add_test__ifdef_xml_dtd(tc_basic, test_empty_foreign_dtd);
11326 tcase_add_test(tc_basic, test_set_base);
11327 tcase_add_test(tc_basic, test_attributes);
11328 tcase_add_test(tc_basic, test_reset_in_entity);
11329 tcase_add_test(tc_basic, test_resume_invalid_parse);
11330 tcase_add_test(tc_basic, test_resume_resuspended);
11331 tcase_add_test(tc_basic, test_cdata_default);
11332 tcase_add_test(tc_basic, test_subordinate_reset);
11333 tcase_add_test(tc_basic, test_subordinate_suspend);
11334 tcase_add_test(tc_basic, test_subordinate_xdecl_suspend);
11335 tcase_add_test(tc_basic, test_subordinate_xdecl_abort);
11336 tcase_add_test(tc_basic, test_explicit_encoding);
11337 tcase_add_test(tc_basic, test_trailing_cr);
11338 tcase_add_test(tc_basic, test_ext_entity_trailing_cr);
11339 tcase_add_test(tc_basic, test_trailing_rsqb);
11340 tcase_add_test(tc_basic, test_ext_entity_trailing_rsqb);
11341 tcase_add_test(tc_basic, test_ext_entity_good_cdata);
11342 tcase_add_test__ifdef_xml_dtd(tc_basic, test_user_parameters);
11343 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_ref_parameter);
11344 tcase_add_test(tc_basic, test_empty_parse);
11345 tcase_add_test(tc_basic, test_get_buffer_1);
11346 tcase_add_test(tc_basic, test_get_buffer_2);
11347 tcase_add_test(tc_basic, test_byte_info_at_end);
11348 tcase_add_test(tc_basic, test_byte_info_at_error);
11349 tcase_add_test(tc_basic, test_byte_info_at_cdata);
11350 tcase_add_test(tc_basic, test_predefined_entities);
11351 tcase_add_test__ifdef_xml_dtd(tc_basic, test_invalid_tag_in_dtd);
11352 tcase_add_test(tc_basic, test_not_predefined_entities);
11353 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section);
11354 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section_utf16);
11355 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section_utf16_be);
11356 tcase_add_test__ifdef_xml_dtd(tc_basic, test_bad_ignore_section);
11357 tcase_add_test__ifdef_xml_dtd(tc_basic, test_external_entity_values);
11358 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_not_standalone);
11359 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_value_abort);
11360 tcase_add_test(tc_basic, test_bad_public_doctype);
11361 tcase_add_test(tc_basic, test_attribute_enum_value);
11362 tcase_add_test(tc_basic, test_predefined_entity_redefinition);
11363 tcase_add_test__ifdef_xml_dtd(tc_basic, test_dtd_stop_processing);
11364 tcase_add_test(tc_basic, test_public_notation_no_sysid);
11365 tcase_add_test(tc_basic, test_nested_groups);
11366 tcase_add_test(tc_basic, test_group_choice);
11367 tcase_add_test(tc_basic, test_standalone_parameter_entity);
11368 tcase_add_test__ifdef_xml_dtd(tc_basic, test_skipped_parameter_entity);
11369 tcase_add_test__ifdef_xml_dtd(tc_basic,
11370 test_recursive_external_parameter_entity);
11371 tcase_add_test(tc_basic, test_undefined_ext_entity_in_external_dtd);
11372 tcase_add_test(tc_basic, test_suspend_xdecl);
11373 tcase_add_test(tc_basic, test_abort_epilog);
11374 tcase_add_test(tc_basic, test_abort_epilog_2);
11375 tcase_add_test(tc_basic, test_suspend_epilog);
11376 tcase_add_test(tc_basic, test_suspend_in_sole_empty_tag);
11377 tcase_add_test(tc_basic, test_unfinished_epilog);
11378 tcase_add_test(tc_basic, test_partial_char_in_epilog);
11379 tcase_add_test(tc_basic, test_hash_collision);
11380 tcase_add_test__ifdef_xml_dtd(tc_basic, test_suspend_resume_internal_entity);
11381 tcase_add_test__ifdef_xml_dtd(tc_basic, test_resume_entity_with_syntax_error);
11382 tcase_add_test__ifdef_xml_dtd(tc_basic, test_suspend_resume_parameter_entity);
11383 tcase_add_test(tc_basic, test_restart_on_error);
11384 tcase_add_test(tc_basic, test_reject_lt_in_attribute_value);
11385 tcase_add_test(tc_basic, test_reject_unfinished_param_in_att_value);
11386 tcase_add_test(tc_basic, test_trailing_cr_in_att_value);
11387 tcase_add_test(tc_basic, test_standalone_internal_entity);
11388 tcase_add_test(tc_basic, test_skipped_external_entity);
11389 tcase_add_test(tc_basic, test_skipped_null_loaded_ext_entity);
11390 tcase_add_test(tc_basic, test_skipped_unloaded_ext_entity);
11391 tcase_add_test__ifdef_xml_dtd(tc_basic, test_param_entity_with_trailing_cr);
11392 tcase_add_test(tc_basic, test_invalid_character_entity);
11393 tcase_add_test(tc_basic, test_invalid_character_entity_2);
11394 tcase_add_test(tc_basic, test_invalid_character_entity_3);
11395 tcase_add_test(tc_basic, test_invalid_character_entity_4);
11396 tcase_add_test(tc_basic, test_pi_handled_in_default);
11397 tcase_add_test(tc_basic, test_comment_handled_in_default);
11398 tcase_add_test(tc_basic, test_pi_yml);
11399 tcase_add_test(tc_basic, test_pi_xnl);
11400 tcase_add_test(tc_basic, test_pi_xmm);
11401 tcase_add_test(tc_basic, test_utf16_pi);
11402 tcase_add_test(tc_basic, test_utf16_be_pi);
11403 tcase_add_test(tc_basic, test_utf16_be_comment);
11404 tcase_add_test(tc_basic, test_utf16_le_comment);
11405 tcase_add_test(tc_basic, test_missing_encoding_conversion_fn);
11406 tcase_add_test(tc_basic, test_failing_encoding_conversion_fn);
11407 tcase_add_test(tc_basic, test_unknown_encoding_success);
11408 tcase_add_test(tc_basic, test_unknown_encoding_bad_name);
11409 tcase_add_test(tc_basic, test_unknown_encoding_bad_name_2);
11410 tcase_add_test(tc_basic, test_unknown_encoding_long_name_1);
11411 tcase_add_test(tc_basic, test_unknown_encoding_long_name_2);
11412 tcase_add_test(tc_basic, test_invalid_unknown_encoding);
11413 tcase_add_test(tc_basic, test_unknown_ascii_encoding_ok);
11414 tcase_add_test(tc_basic, test_unknown_ascii_encoding_fail);
11415 tcase_add_test(tc_basic, test_unknown_encoding_invalid_length);
11416 tcase_add_test(tc_basic, test_unknown_encoding_invalid_topbit);
11417 tcase_add_test(tc_basic, test_unknown_encoding_invalid_surrogate);
11418 tcase_add_test(tc_basic, test_unknown_encoding_invalid_high);
11419 tcase_add_test(tc_basic, test_unknown_encoding_invalid_attr_value);
11420 tcase_add_test(tc_basic, test_ext_entity_latin1_utf16le_bom);
11421 tcase_add_test(tc_basic, test_ext_entity_latin1_utf16be_bom);
11422 tcase_add_test(tc_basic, test_ext_entity_latin1_utf16le_bom2);
11423 tcase_add_test(tc_basic, test_ext_entity_latin1_utf16be_bom2);
11424 tcase_add_test(tc_basic, test_ext_entity_utf16_be);
11425 tcase_add_test(tc_basic, test_ext_entity_utf16_le);
11426 tcase_add_test(tc_basic, test_ext_entity_utf16_unknown);
11427 tcase_add_test(tc_basic, test_ext_entity_utf8_non_bom);
11428 tcase_add_test(tc_basic, test_utf8_in_cdata_section);
11429 tcase_add_test(tc_basic, test_utf8_in_cdata_section_2);
11430 tcase_add_test(tc_basic, test_trailing_spaces_in_elements);
11431 tcase_add_test(tc_basic, test_utf16_attribute);
11432 tcase_add_test(tc_basic, test_utf16_second_attr);
11433 tcase_add_test(tc_basic, test_attr_after_solidus);
11434 tcase_add_test__ifdef_xml_dtd(tc_basic, test_utf16_pe);
11435 tcase_add_test(tc_basic, test_bad_attr_desc_keyword);
11436 tcase_add_test(tc_basic, test_bad_attr_desc_keyword_utf16);
11437 tcase_add_test(tc_basic, test_bad_doctype);
11438 tcase_add_test(tc_basic, test_bad_doctype_utf16);
11439 tcase_add_test(tc_basic, test_bad_doctype_plus);
11440 tcase_add_test(tc_basic, test_bad_doctype_star);
11441 tcase_add_test(tc_basic, test_bad_doctype_query);
11442 tcase_add_test__ifdef_xml_dtd(tc_basic, test_unknown_encoding_bad_ignore);
11443 tcase_add_test(tc_basic, test_entity_in_utf16_be_attr);
11444 tcase_add_test(tc_basic, test_entity_in_utf16_le_attr);
11445 tcase_add_test__ifdef_xml_dtd(tc_basic, test_entity_public_utf16_be);
11446 tcase_add_test__ifdef_xml_dtd(tc_basic, test_entity_public_utf16_le);
11447 tcase_add_test(tc_basic, test_short_doctype);
11448 tcase_add_test(tc_basic, test_short_doctype_2);
11449 tcase_add_test(tc_basic, test_short_doctype_3);
11450 tcase_add_test(tc_basic, test_long_doctype);
11451 tcase_add_test(tc_basic, test_bad_entity);
11452 tcase_add_test(tc_basic, test_bad_entity_2);
11453 tcase_add_test(tc_basic, test_bad_entity_3);
11454 tcase_add_test(tc_basic, test_bad_entity_4);
11455 tcase_add_test(tc_basic, test_bad_notation);
11456 tcase_add_test(tc_basic, test_default_doctype_handler);
11457 tcase_add_test(tc_basic, test_empty_element_abort);
11458
11459 suite_add_tcase(s, tc_namespace);
11460 tcase_add_checked_fixture(tc_namespace, namespace_setup, namespace_teardown);
11461 tcase_add_test(tc_namespace, test_return_ns_triplet);
11462 tcase_add_test(tc_namespace, test_ns_tagname_overwrite);
11463 tcase_add_test(tc_namespace, test_ns_tagname_overwrite_triplet);
11464 tcase_add_test(tc_namespace, test_start_ns_clears_start_element);
11465 tcase_add_test__ifdef_xml_dtd(tc_namespace,
11466 test_default_ns_from_ext_subset_and_ext_ge);
11467 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_1);
11468 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_2);
11469 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_3);
11470 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_4);
11471 tcase_add_test(tc_namespace, test_ns_unbound_prefix);
11472 tcase_add_test(tc_namespace, test_ns_default_with_empty_uri);
11473 tcase_add_test(tc_namespace, test_ns_duplicate_attrs_diff_prefixes);
11474 tcase_add_test(tc_namespace, test_ns_duplicate_hashes);
11475 tcase_add_test(tc_namespace, test_ns_unbound_prefix_on_attribute);
11476 tcase_add_test(tc_namespace, test_ns_unbound_prefix_on_element);
11477 tcase_add_test(tc_namespace, test_ns_parser_reset);
11478 tcase_add_test(tc_namespace, test_ns_long_element);
11479 tcase_add_test(tc_namespace, test_ns_mixed_prefix_atts);
11480 tcase_add_test(tc_namespace, test_ns_extend_uri_buffer);
11481 tcase_add_test(tc_namespace, test_ns_reserved_attributes);
11482 tcase_add_test(tc_namespace, test_ns_reserved_attributes_2);
11483 tcase_add_test(tc_namespace, test_ns_extremely_long_prefix);
11484 tcase_add_test(tc_namespace, test_ns_unknown_encoding_success);
11485 tcase_add_test(tc_namespace, test_ns_double_colon);
11486 tcase_add_test(tc_namespace, test_ns_double_colon_element);
11487 tcase_add_test(tc_namespace, test_ns_bad_attr_leafname);
11488 tcase_add_test(tc_namespace, test_ns_bad_element_leafname);
11489 tcase_add_test(tc_namespace, test_ns_utf16_leafname);
11490 tcase_add_test(tc_namespace, test_ns_utf16_element_leafname);
11491 tcase_add_test(tc_namespace, test_ns_utf16_doctype);
11492 tcase_add_test(tc_namespace, test_ns_invalid_doctype);
11493 tcase_add_test(tc_namespace, test_ns_double_colon_doctype);
11494
11495 suite_add_tcase(s, tc_misc);
11496 tcase_add_checked_fixture(tc_misc, NULL, basic_teardown);
11497 tcase_add_test(tc_misc, test_misc_alloc_create_parser);
11498 tcase_add_test(tc_misc, test_misc_alloc_create_parser_with_encoding);
11499 tcase_add_test(tc_misc, test_misc_null_parser);
11500 tcase_add_test(tc_misc, test_misc_error_string);
11501 tcase_add_test(tc_misc, test_misc_version);
11502 tcase_add_test(tc_misc, test_misc_features);
11503 tcase_add_test(tc_misc, test_misc_attribute_leak);
11504 tcase_add_test(tc_misc, test_misc_utf16le);
11505 tcase_add_test(tc_misc, test_misc_stop_during_end_handler_issue_240_1);
11506 tcase_add_test(tc_misc, test_misc_stop_during_end_handler_issue_240_2);
11507 tcase_add_test__ifdef_xml_dtd(
11508 tc_misc, test_misc_deny_internal_entity_closing_doctype_issue_317);
11509
11510 suite_add_tcase(s, tc_alloc);
11511 tcase_add_checked_fixture(tc_alloc, alloc_setup, alloc_teardown);
11512 tcase_add_test(tc_alloc, test_alloc_parse_xdecl);
11513 tcase_add_test(tc_alloc, test_alloc_parse_xdecl_2);
11514 tcase_add_test(tc_alloc, test_alloc_parse_pi);
11515 tcase_add_test(tc_alloc, test_alloc_parse_pi_2);
11516 tcase_add_test(tc_alloc, test_alloc_parse_pi_3);
11517 tcase_add_test(tc_alloc, test_alloc_parse_comment);
11518 tcase_add_test(tc_alloc, test_alloc_parse_comment_2);
11519 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_create_external_parser);
11520 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_run_external_parser);
11521 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_dtd_copy_default_atts);
11522 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_external_entity);
11523 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_ext_entity_set_encoding);
11524 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_internal_entity);
11525 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_dtd_default_handling);
11526 tcase_add_test(tc_alloc, test_alloc_explicit_encoding);
11527 tcase_add_test(tc_alloc, test_alloc_set_base);
11528 tcase_add_test(tc_alloc, test_alloc_realloc_buffer);
11529 tcase_add_test(tc_alloc, test_alloc_ext_entity_realloc_buffer);
11530 tcase_add_test(tc_alloc, test_alloc_realloc_many_attributes);
11531 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_public_entity_value);
11532 tcase_add_test__ifdef_xml_dtd(tc_alloc,
11533 test_alloc_realloc_subst_public_entity_value);
11534 tcase_add_test(tc_alloc, test_alloc_parse_public_doctype);
11535 tcase_add_test(tc_alloc, test_alloc_parse_public_doctype_long_name);
11536 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_set_foreign_dtd);
11537 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_attribute_enum_value);
11538 tcase_add_test__ifdef_xml_dtd(tc_alloc,
11539 test_alloc_realloc_attribute_enum_value);
11540 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_implied_attribute);
11541 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_default_attribute);
11542 tcase_add_test(tc_alloc, test_alloc_notation);
11543 tcase_add_test(tc_alloc, test_alloc_public_notation);
11544 tcase_add_test(tc_alloc, test_alloc_system_notation);
11545 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_nested_groups);
11546 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_nested_groups);
11547 tcase_add_test(tc_alloc, test_alloc_large_group);
11548 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_group_choice);
11549 tcase_add_test(tc_alloc, test_alloc_pi_in_epilog);
11550 tcase_add_test(tc_alloc, test_alloc_comment_in_epilog);
11551 tcase_add_test__ifdef_xml_dtd(tc_alloc,
11552 test_alloc_realloc_long_attribute_value);
11553 tcase_add_test(tc_alloc, test_alloc_attribute_whitespace);
11554 tcase_add_test(tc_alloc, test_alloc_attribute_predefined_entity);
11555 tcase_add_test(tc_alloc, test_alloc_long_attr_default_with_char_ref);
11556 tcase_add_test(tc_alloc, test_alloc_long_attr_value);
11557 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_nested_entities);
11558 tcase_add_test__ifdef_xml_dtd(tc_alloc,
11559 test_alloc_realloc_param_entity_newline);
11560 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_ce_extends_pe);
11561 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_attributes);
11562 tcase_add_test(tc_alloc, test_alloc_long_doc_name);
11563 tcase_add_test(tc_alloc, test_alloc_long_base);
11564 tcase_add_test(tc_alloc, test_alloc_long_public_id);
11565 tcase_add_test(tc_alloc, test_alloc_long_entity_value);
11566 tcase_add_test(tc_alloc, test_alloc_long_notation);
11567
11568 suite_add_tcase(s, tc_nsalloc);
11569 tcase_add_checked_fixture(tc_nsalloc, nsalloc_setup, nsalloc_teardown);
11570 tcase_add_test(tc_nsalloc, test_nsalloc_xmlns);
11571 tcase_add_test(tc_nsalloc, test_nsalloc_parse_buffer);
11572 tcase_add_test(tc_nsalloc, test_nsalloc_long_prefix);
11573 tcase_add_test(tc_nsalloc, test_nsalloc_long_uri);
11574 tcase_add_test(tc_nsalloc, test_nsalloc_long_attr);
11575 tcase_add_test(tc_nsalloc, test_nsalloc_long_attr_prefix);
11576 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_attributes);
11577 tcase_add_test(tc_nsalloc, test_nsalloc_long_element);
11578 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_binding_uri);
11579 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_prefix);
11580 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_longer_prefix);
11581 tcase_add_test(tc_nsalloc, test_nsalloc_long_namespace);
11582 tcase_add_test(tc_nsalloc, test_nsalloc_less_long_namespace);
11583 tcase_add_test(tc_nsalloc, test_nsalloc_long_context);
11584 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context);
11585 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_2);
11586 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_3);
11587 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_4);
11588 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_5);
11589 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_6);
11590 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_7);
11591 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_ge_name);
11592 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_in_dtd);
11593 tcase_add_test(tc_nsalloc, test_nsalloc_long_default_in_ext);
11594 tcase_add_test(tc_nsalloc, test_nsalloc_long_systemid_in_ext);
11595 tcase_add_test(tc_nsalloc, test_nsalloc_prefixed_element);
11596
11597 return s;
11598 }
11599
11600 int
main(int argc,char * argv[])11601 main(int argc, char *argv[]) {
11602 int i, nf;
11603 int verbosity = CK_NORMAL;
11604 Suite *s = make_suite();
11605 SRunner *sr = srunner_create(s);
11606
11607 /* run the tests for internal helper functions */
11608 testhelper_is_whitespace_normalized();
11609
11610 for (i = 1; i < argc; ++i) {
11611 char *opt = argv[i];
11612 if (strcmp(opt, "-v") == 0 || strcmp(opt, "--verbose") == 0)
11613 verbosity = CK_VERBOSE;
11614 else if (strcmp(opt, "-q") == 0 || strcmp(opt, "--quiet") == 0)
11615 verbosity = CK_SILENT;
11616 else {
11617 fprintf(stderr, "runtests: unknown option '%s'\n", opt);
11618 return 2;
11619 }
11620 }
11621 if (verbosity != CK_SILENT)
11622 printf("Expat version: %" XML_FMT_STR "\n", XML_ExpatVersion());
11623 srunner_run_all(sr, verbosity);
11624 nf = srunner_ntests_failed(sr);
11625 srunner_free(sr);
11626
11627 return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
11628 }
11629