1 /* XML handler functions for the Expat test suite
2 __ __ _
3 ___\ \/ /_ __ __ _| |_
4 / _ \\ /| '_ \ / _` | __|
5 | __// \| |_) | (_| | |_
6 \___/_/\_\ .__/ \__,_|\__|
7 |_| XML parser
8
9 Copyright (c) 2001-2006 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
10 Copyright (c) 2003 Greg Stein <gstein@users.sourceforge.net>
11 Copyright (c) 2005-2007 Steven Solie <steven@solie.ca>
12 Copyright (c) 2005-2012 Karl Waclawek <karl@waclawek.net>
13 Copyright (c) 2016-2026 Sebastian Pipping <sebastian@pipping.org>
14 Copyright (c) 2017-2022 Rhodri James <rhodri@wildebeest.org.uk>
15 Copyright (c) 2017 Joe Orton <jorton@redhat.com>
16 Copyright (c) 2017 José Gutiérrez de la Concha <jose@zeroc.com>
17 Copyright (c) 2018 Marco Maggi <marco.maggi-ipsu@poste.it>
18 Copyright (c) 2019 David Loffredo <loffredo@steptools.com>
19 Copyright (c) 2020 Tim Gates <tim.gates@iress.com>
20 Copyright (c) 2021 Donghee Na <donghee.na@python.org>
21 Copyright (c) 2023-2024 Sony Corporation / Snild Dolkow <snild@sony.com>
22 Copyright (c) 2026 Matthew Fernandez <matthew.fernandez@gmail.com>
23 Copyright (c) 2026 Berkay Eren Ürün <berkay.ueruen@siemens.com>
24 Licensed under the MIT license:
25
26 Permission is hereby granted, free of charge, to any person obtaining
27 a copy of this software and associated documentation files (the
28 "Software"), to deal in the Software without restriction, including
29 without limitation the rights to use, copy, modify, merge, publish,
30 distribute, sublicense, and/or sell copies of the Software, and to permit
31 persons to whom the Software is furnished to do so, subject to the
32 following conditions:
33
34 The above copyright notice and this permission notice shall be included
35 in all copies or substantial portions of the Software.
36
37 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
38 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
39 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
40 NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
41 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
42 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
43 USE OR OTHER DEALINGS IN THE SOFTWARE.
44 */
45
46 #if defined(NDEBUG)
47 # undef NDEBUG /* because test suite relies on assert(...) at the moment */
48 #endif
49
50 #include <stdint.h>
51 #include <stdio.h>
52 #include <string.h>
53 #include <assert.h>
54
55 #include "expat_config.h"
56
57 #include "expat.h"
58 #include "internal.h"
59 #include "chardata.h"
60 #include "structdata.h"
61 #include "common.h"
62 #include "handlers.h"
63
64 /* Global variables for user parameter settings tests */
65 /* Variable holding the expected handler userData */
66 const void *g_handler_data = NULL;
67 /* Count of the number of times the comment handler has been invoked */
68 int g_comment_count = 0;
69 /* Count of the number of skipped entities */
70 int g_skip_count = 0;
71 /* Count of the number of times the XML declaration handler is invoked */
72 int g_xdecl_count = 0;
73
74 /* Start/End Element Handlers */
75
76 void XMLCALL
start_element_event_handler(void * userData,const XML_Char * name,const XML_Char ** atts)77 start_element_event_handler(void *userData, const XML_Char *name,
78 const XML_Char **atts) {
79 UNUSED_P(atts);
80 CharData_AppendXMLChars((CharData *)userData, name, -1);
81 }
82
83 void XMLCALL
end_element_event_handler(void * userData,const XML_Char * name)84 end_element_event_handler(void *userData, const XML_Char *name) {
85 CharData *storage = (CharData *)userData;
86 CharData_AppendXMLChars(storage, XCS("/"), 1);
87 CharData_AppendXMLChars(storage, name, -1);
88 }
89
90 void XMLCALL
start_element_event_handler2(void * userData,const XML_Char * name,const XML_Char ** attr)91 start_element_event_handler2(void *userData, const XML_Char *name,
92 const XML_Char **attr) {
93 StructData *storage = (StructData *)userData;
94 UNUSED_P(attr);
95 StructData_AddItem(storage, name, (int)XML_GetCurrentColumnNumber(g_parser),
96 (int)XML_GetCurrentLineNumber(g_parser), STRUCT_START_TAG);
97 }
98
99 void XMLCALL
end_element_event_handler2(void * userData,const XML_Char * name)100 end_element_event_handler2(void *userData, const XML_Char *name) {
101 StructData *storage = (StructData *)userData;
102 StructData_AddItem(storage, name, (int)XML_GetCurrentColumnNumber(g_parser),
103 (int)XML_GetCurrentLineNumber(g_parser), STRUCT_END_TAG);
104 }
105
106 void XMLCALL
counting_start_element_handler(void * userData,const XML_Char * name,const XML_Char ** atts)107 counting_start_element_handler(void *userData, const XML_Char *name,
108 const XML_Char **atts) {
109 ParserAndElementInfo *const parserAndElementInfos
110 = (ParserAndElementInfo *)userData;
111 ElementInfo *info = parserAndElementInfos->info;
112 AttrInfo *attr;
113 int count, id, i;
114
115 while (info->name != NULL) {
116 if (! xcstrcmp(name, info->name))
117 break;
118 info++;
119 }
120 if (info->name == NULL)
121 fail("Element not recognised");
122 /* The attribute count is twice what you might expect. It is a
123 * count of items in atts, an array which contains alternating
124 * attribute names and attribute values. For the naive user this
125 * is possibly a little unexpected, but it is what the
126 * documentation in expat.h tells us to expect.
127 */
128 count = XML_GetSpecifiedAttributeCount(parserAndElementInfos->parser);
129 if (info->attr_count * 2 != count) {
130 fail("Not got expected attribute count");
131 return;
132 }
133 id = XML_GetIdAttributeIndex(parserAndElementInfos->parser);
134 if (id == -1 && info->id_name != NULL) {
135 fail("ID not present");
136 return;
137 }
138 if (id != -1 && xcstrcmp(atts[id], info->id_name) != 0) {
139 fail("ID does not have the correct name");
140 return;
141 }
142 for (i = 0; i < info->attr_count + info->default_attr_count; i++) {
143 attr = info->attributes;
144 while (attr->name != NULL) {
145 if (! xcstrcmp(atts[0], attr->name))
146 break;
147 attr++;
148 }
149 if (attr->name == NULL) {
150 fail("Attribute not recognised");
151 return;
152 }
153 if (xcstrcmp(atts[1], attr->value) != 0) {
154 fail("Attribute has wrong value");
155 return;
156 }
157 /* Remember, two entries in atts per attribute (see above) */
158 atts += 2;
159 }
160
161 // Self-test that the test case's list of expected attributes is complete
162 assert_true(atts[0] == NULL);
163 }
164
165 void XMLCALL
suspending_end_handler(void * userData,const XML_Char * s)166 suspending_end_handler(void *userData, const XML_Char *s) {
167 UNUSED_P(s);
168 XML_StopParser((XML_Parser)userData, 1);
169 }
170
171 void XMLCALL
start_element_suspender(void * userData,const XML_Char * name,const XML_Char ** atts)172 start_element_suspender(void *userData, const XML_Char *name,
173 const XML_Char **atts) {
174 UNUSED_P(userData);
175 UNUSED_P(atts);
176 if (! xcstrcmp(name, XCS("suspend")))
177 XML_StopParser(g_parser, XML_TRUE);
178 if (! xcstrcmp(name, XCS("abort")))
179 XML_StopParser(g_parser, XML_FALSE);
180 }
181
182 /* Check that an element name and attribute name match the expected values.
183 The expected values are passed as an array reference of string pointers
184 provided as the userData argument; the first is the expected
185 element name, and the second is the expected attribute name.
186 */
187 int g_triplet_start_flag = XML_FALSE;
188 int g_triplet_end_flag = XML_FALSE;
189
190 void XMLCALL
triplet_start_checker(void * userData,const XML_Char * name,const XML_Char ** atts)191 triplet_start_checker(void *userData, const XML_Char *name,
192 const XML_Char **atts) {
193 XML_Char **elemstr = (XML_Char **)userData;
194 char buffer[1024];
195 if (xcstrcmp(elemstr[0], name) != 0) {
196 snprintf(buffer, sizeof(buffer),
197 "unexpected start string: '%" XML_FMT_STR "'", name);
198 fail(buffer);
199 }
200 if (xcstrcmp(elemstr[1], atts[0]) != 0) {
201 snprintf(buffer, sizeof(buffer),
202 "unexpected attribute string: '%" XML_FMT_STR "'", atts[0]);
203 fail(buffer);
204 }
205 g_triplet_start_flag = XML_TRUE;
206 }
207
208 /* Check that the element name passed to the end-element handler matches
209 the expected value. The expected value is passed as the first element
210 in an array of strings passed as the userData argument.
211 */
212 void XMLCALL
triplet_end_checker(void * userData,const XML_Char * name)213 triplet_end_checker(void *userData, const XML_Char *name) {
214 XML_Char **elemstr = (XML_Char **)userData;
215 if (xcstrcmp(elemstr[0], name) != 0) {
216 char buffer[1024];
217 snprintf(buffer, sizeof(buffer),
218 "unexpected end string: '%" XML_FMT_STR "'", name);
219 fail(buffer);
220 }
221 g_triplet_end_flag = XML_TRUE;
222 }
223
224 void XMLCALL
overwrite_start_checker(void * userData,const XML_Char * name,const XML_Char ** atts)225 overwrite_start_checker(void *userData, const XML_Char *name,
226 const XML_Char **atts) {
227 CharData *storage = (CharData *)userData;
228 CharData_AppendXMLChars(storage, XCS("start "), 6);
229 CharData_AppendXMLChars(storage, name, -1);
230 while (*atts != NULL) {
231 CharData_AppendXMLChars(storage, XCS("\nattribute "), 11);
232 CharData_AppendXMLChars(storage, *atts, -1);
233 atts += 2;
234 }
235 CharData_AppendXMLChars(storage, XCS("\n"), 1);
236 }
237
238 void XMLCALL
overwrite_end_checker(void * userData,const XML_Char * name)239 overwrite_end_checker(void *userData, const XML_Char *name) {
240 CharData *storage = (CharData *)userData;
241 CharData_AppendXMLChars(storage, XCS("end "), 4);
242 CharData_AppendXMLChars(storage, name, -1);
243 CharData_AppendXMLChars(storage, XCS("\n"), 1);
244 }
245
246 void XMLCALL
start_element_fail(void * userData,const XML_Char * name,const XML_Char ** atts)247 start_element_fail(void *userData, const XML_Char *name,
248 const XML_Char **atts) {
249 UNUSED_P(userData);
250 UNUSED_P(name);
251 UNUSED_P(atts);
252
253 /* We should never get here. */
254 fail("should never reach start_element_fail()");
255 }
256
257 void XMLCALL
start_ns_clearing_start_element(void * userData,const XML_Char * prefix,const XML_Char * uri)258 start_ns_clearing_start_element(void *userData, const XML_Char *prefix,
259 const XML_Char *uri) {
260 UNUSED_P(prefix);
261 UNUSED_P(uri);
262 XML_SetStartElementHandler((XML_Parser)userData, NULL);
263 }
264
265 void XMLCALL
start_element_issue_240(void * userData,const XML_Char * name,const XML_Char ** atts)266 start_element_issue_240(void *userData, const XML_Char *name,
267 const XML_Char **atts) {
268 DataIssue240 *mydata = (DataIssue240 *)userData;
269 UNUSED_P(name);
270 UNUSED_P(atts);
271 mydata->deep++;
272 }
273
274 void XMLCALL
end_element_issue_240(void * userData,const XML_Char * name)275 end_element_issue_240(void *userData, const XML_Char *name) {
276 DataIssue240 *mydata = (DataIssue240 *)userData;
277
278 UNUSED_P(name);
279 mydata->deep--;
280 if (mydata->deep == 0) {
281 XML_StopParser(mydata->parser, 0);
282 }
283 }
284
285 /* Text encoding handlers */
286
287 int XMLCALL
UnknownEncodingHandler(void * data,const XML_Char * encoding,XML_Encoding * info)288 UnknownEncodingHandler(void *data, const XML_Char *encoding,
289 XML_Encoding *info) {
290 UNUSED_P(data);
291 if (xcstrcmp(encoding, XCS("unsupported-encoding")) == 0) {
292 int i;
293 for (i = 0; i < 256; ++i)
294 info->map[i] = i;
295 info->data = NULL;
296 info->convert = NULL;
297 info->release = NULL;
298 return XML_STATUS_OK;
299 }
300 return XML_STATUS_ERROR;
301 }
302
303 static void
dummy_release(void * data)304 dummy_release(void *data) {
305 UNUSED_P(data);
306 }
307
308 int XMLCALL
UnrecognisedEncodingHandler(void * data,const XML_Char * encoding,XML_Encoding * info)309 UnrecognisedEncodingHandler(void *data, const XML_Char *encoding,
310 XML_Encoding *info) {
311 UNUSED_P(data);
312 UNUSED_P(encoding);
313 info->data = NULL;
314 info->convert = NULL;
315 info->release = dummy_release;
316 return XML_STATUS_ERROR;
317 }
318
319 int XMLCALL
unknown_released_encoding_handler(void * data,const XML_Char * encoding,XML_Encoding * info)320 unknown_released_encoding_handler(void *data, const XML_Char *encoding,
321 XML_Encoding *info) {
322 UNUSED_P(data);
323 if (! xcstrcmp(encoding, XCS("unsupported-encoding"))) {
324 int i;
325
326 for (i = 0; i < 256; i++)
327 info->map[i] = i;
328 info->data = NULL;
329 info->convert = NULL;
330 info->release = dummy_release;
331 return XML_STATUS_OK;
332 }
333 return XML_STATUS_ERROR;
334 }
335
336 static int XMLCALL
failing_converter(void * data,const char * s)337 failing_converter(void *data, const char *s) {
338 UNUSED_P(data);
339 UNUSED_P(s);
340 /* Always claim to have failed */
341 return -1;
342 }
343
344 static int XMLCALL
prefix_converter(void * data,const char * s)345 prefix_converter(void *data, const char *s) {
346 UNUSED_P(data);
347 /* If the first byte is 0xff, raise an error */
348 if (s[0] == (char)-1)
349 return -1;
350 /* Just add the low bits of the first byte to the second */
351 return (s[1] + (s[0] & 0x7f)) & 0x01ff;
352 }
353
354 int XMLCALL
MiscEncodingHandler(void * data,const XML_Char * encoding,XML_Encoding * info)355 MiscEncodingHandler(void *data, const XML_Char *encoding, XML_Encoding *info) {
356 int i;
357 int high_map = -2; /* Assume a 2-byte sequence */
358
359 if (! xcstrcmp(encoding, XCS("invalid-9"))
360 || ! xcstrcmp(encoding, XCS("ascii-like"))
361 || ! xcstrcmp(encoding, XCS("invalid-len"))
362 || ! xcstrcmp(encoding, XCS("invalid-a"))
363 || ! xcstrcmp(encoding, XCS("invalid-surrogate"))
364 || ! xcstrcmp(encoding, XCS("invalid-high")))
365 high_map = -1;
366
367 for (i = 0; i < 128; ++i)
368 info->map[i] = i;
369 for (; i < 256; ++i)
370 info->map[i] = high_map;
371
372 /* If required, put an invalid value in the ASCII entries */
373 if (! xcstrcmp(encoding, XCS("invalid-9")))
374 info->map[9] = 5;
375 /* If required, have a top-bit set character starts a 5-byte sequence */
376 if (! xcstrcmp(encoding, XCS("invalid-len")))
377 info->map[0x81] = -5;
378 /* If required, make a top-bit set character a valid ASCII character */
379 if (! xcstrcmp(encoding, XCS("invalid-a")))
380 info->map[0x82] = 'a';
381 /* If required, give a top-bit set character a forbidden value,
382 * what would otherwise be the first of a surrogate pair.
383 */
384 if (! xcstrcmp(encoding, XCS("invalid-surrogate")))
385 info->map[0x83] = 0xd801;
386 /* If required, give a top-bit set character too high a value */
387 if (! xcstrcmp(encoding, XCS("invalid-high")))
388 info->map[0x84] = 0x010101;
389
390 info->data = data;
391 info->release = NULL;
392 if (! xcstrcmp(encoding, XCS("failing-conv")))
393 info->convert = failing_converter;
394 else if (! xcstrcmp(encoding, XCS("prefix-conv")))
395 info->convert = prefix_converter;
396 else
397 info->convert = NULL;
398 return XML_STATUS_OK;
399 }
400
401 int XMLCALL
long_encoding_handler(void * userData,const XML_Char * encoding,XML_Encoding * info)402 long_encoding_handler(void *userData, const XML_Char *encoding,
403 XML_Encoding *info) {
404 int i;
405
406 UNUSED_P(userData);
407 UNUSED_P(encoding);
408 for (i = 0; i < 256; i++)
409 info->map[i] = i;
410 info->data = NULL;
411 info->convert = NULL;
412 info->release = NULL;
413 return XML_STATUS_OK;
414 }
415
416 int XMLCALL
user_data_checking_unknown_encoding_handler(void * userData,const XML_Char * encoding,XML_Encoding * info)417 user_data_checking_unknown_encoding_handler(void *userData,
418 const XML_Char *encoding,
419 XML_Encoding *info) {
420 const intptr_t number = (intptr_t)userData;
421 assert_true(number == 0xC0FFEE);
422 return long_encoding_handler(userData, encoding, info);
423 }
424
425 /* External Entity Handlers */
426
427 int XMLCALL
external_entity_optioner(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)428 external_entity_optioner(XML_Parser parser, const XML_Char *context,
429 const XML_Char *base, const XML_Char *systemId,
430 const XML_Char *publicId) {
431 ExtOption *options = XML_GetUserData(parser);
432 XML_Parser ext_parser;
433
434 UNUSED_P(base);
435 UNUSED_P(publicId);
436 while (options->parse_text != NULL) {
437 if (! xcstrcmp(systemId, options->system_id)) {
438 enum XML_Status rc;
439 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
440 if (ext_parser == NULL)
441 return XML_STATUS_ERROR;
442 rc = _XML_Parse_SINGLE_BYTES(ext_parser, options->parse_text,
443 (int)strlen(options->parse_text), XML_TRUE);
444 XML_ParserFree(ext_parser);
445 return rc;
446 }
447 options++;
448 }
449 fail("No suitable option found");
450 return XML_STATUS_ERROR;
451 }
452
453 int XMLCALL
external_entity_loader(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)454 external_entity_loader(XML_Parser parser, const XML_Char *context,
455 const XML_Char *base, const XML_Char *systemId,
456 const XML_Char *publicId) {
457 ExtTest *test_data = XML_GetUserData(parser);
458 XML_Parser extparser;
459
460 UNUSED_P(base);
461 UNUSED_P(systemId);
462 UNUSED_P(publicId);
463 extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
464 if (extparser == NULL)
465 fail("Could not create external entity parser.");
466 if (test_data->encoding != NULL) {
467 if (! XML_SetEncoding(extparser, test_data->encoding))
468 fail("XML_SetEncoding() ignored for external entity");
469 }
470 if (_XML_Parse_SINGLE_BYTES(extparser, test_data->parse_text,
471 (int)strlen(test_data->parse_text), XML_TRUE)
472 == XML_STATUS_ERROR) {
473 xml_failure(extparser);
474 return XML_STATUS_ERROR;
475 }
476 XML_ParserFree(extparser);
477 return XML_STATUS_OK;
478 }
479
480 int XMLCALL
external_entity_faulter(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)481 external_entity_faulter(XML_Parser parser, const XML_Char *context,
482 const XML_Char *base, const XML_Char *systemId,
483 const XML_Char *publicId) {
484 XML_Parser ext_parser;
485 ExtFaults *fault = XML_GetUserData(parser);
486
487 UNUSED_P(base);
488 UNUSED_P(systemId);
489 UNUSED_P(publicId);
490 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
491 if (ext_parser == NULL)
492 fail("Could not create external entity parser");
493 if (fault->encoding != NULL) {
494 if (! XML_SetEncoding(ext_parser, fault->encoding))
495 fail("XML_SetEncoding failed");
496 }
497 if (_XML_Parse_SINGLE_BYTES(ext_parser, fault->parse_text,
498 (int)strlen(fault->parse_text), XML_TRUE)
499 != XML_STATUS_ERROR)
500 fail(fault->fail_text);
501 if (XML_GetErrorCode(ext_parser) != fault->error)
502 xml_failure(ext_parser);
503
504 XML_ParserFree(ext_parser);
505 return XML_STATUS_ERROR;
506 }
507
508 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)509 external_entity_null_loader(XML_Parser parser, const XML_Char *context,
510 const XML_Char *base, const XML_Char *systemId,
511 const XML_Char *publicId) {
512 UNUSED_P(parser);
513 UNUSED_P(context);
514 UNUSED_P(base);
515 UNUSED_P(systemId);
516 UNUSED_P(publicId);
517 return XML_STATUS_OK;
518 }
519
520 int XMLCALL
external_entity_resetter(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)521 external_entity_resetter(XML_Parser parser, const XML_Char *context,
522 const XML_Char *base, const XML_Char *systemId,
523 const XML_Char *publicId) {
524 const char *text = "<!ELEMENT doc (#PCDATA)*>";
525 XML_Parser ext_parser;
526 XML_ParsingStatus status;
527
528 UNUSED_P(base);
529 UNUSED_P(systemId);
530 UNUSED_P(publicId);
531 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
532 if (ext_parser == NULL)
533 fail("Could not create external entity parser");
534 XML_GetParsingStatus(ext_parser, &status);
535 if (status.parsing != XML_INITIALIZED) {
536 fail("Parsing status is not INITIALIZED");
537 return XML_STATUS_ERROR;
538 }
539 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
540 == XML_STATUS_ERROR) {
541 xml_failure(parser);
542 return XML_STATUS_ERROR;
543 }
544 XML_GetParsingStatus(ext_parser, &status);
545 if (status.parsing != XML_FINISHED) {
546 fail("Parsing status is not FINISHED");
547 return XML_STATUS_ERROR;
548 }
549 /* Check we can't parse here */
550 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
551 != XML_STATUS_ERROR)
552 fail("Parsing when finished not faulted");
553 if (XML_GetErrorCode(ext_parser) != XML_ERROR_FINISHED)
554 fail("Parsing when finished faulted with wrong code");
555 XML_ParserReset(ext_parser, NULL);
556 XML_GetParsingStatus(ext_parser, &status);
557 if (status.parsing != XML_FINISHED) {
558 fail("Parsing status not still FINISHED");
559 return XML_STATUS_ERROR;
560 }
561 XML_ParserFree(ext_parser);
562 return XML_STATUS_OK;
563 }
564
565 void XMLCALL
entity_suspending_decl_handler(void * userData,const XML_Char * name,XML_Content * model)566 entity_suspending_decl_handler(void *userData, const XML_Char *name,
567 XML_Content *model) {
568 XML_Parser ext_parser = (XML_Parser)userData;
569
570 UNUSED_P(name);
571 if (XML_StopParser(ext_parser, XML_TRUE) != XML_STATUS_ERROR)
572 fail("Attempting to suspend a subordinate parser not faulted");
573 if (XML_GetErrorCode(ext_parser) != XML_ERROR_SUSPEND_PE)
574 fail("Suspending subordinate parser get wrong code");
575 XML_SetElementDeclHandler(ext_parser, NULL);
576 XML_FreeContentModel(g_parser, model);
577 }
578
579 int XMLCALL
external_entity_suspender(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)580 external_entity_suspender(XML_Parser parser, const XML_Char *context,
581 const XML_Char *base, const XML_Char *systemId,
582 const XML_Char *publicId) {
583 const char *text = "<!ELEMENT doc (#PCDATA)*>";
584 XML_Parser ext_parser;
585
586 UNUSED_P(base);
587 UNUSED_P(systemId);
588 UNUSED_P(publicId);
589 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
590 if (ext_parser == NULL)
591 fail("Could not create external entity parser");
592 XML_SetElementDeclHandler(ext_parser, entity_suspending_decl_handler);
593 XML_SetUserData(ext_parser, ext_parser);
594 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
595 == XML_STATUS_ERROR) {
596 xml_failure(ext_parser);
597 return XML_STATUS_ERROR;
598 }
599 XML_ParserFree(ext_parser);
600 return XML_STATUS_OK;
601 }
602
603 void XMLCALL
entity_suspending_xdecl_handler(void * userData,const XML_Char * version,const XML_Char * encoding,int standalone)604 entity_suspending_xdecl_handler(void *userData, const XML_Char *version,
605 const XML_Char *encoding, int standalone) {
606 XML_Parser ext_parser = (XML_Parser)userData;
607
608 UNUSED_P(version);
609 UNUSED_P(encoding);
610 UNUSED_P(standalone);
611 XML_StopParser(ext_parser, g_resumable);
612 XML_SetXmlDeclHandler(ext_parser, NULL);
613 }
614
615 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)616 external_entity_suspend_xmldecl(XML_Parser parser, const XML_Char *context,
617 const XML_Char *base, const XML_Char *systemId,
618 const XML_Char *publicId) {
619 const char *text = "<?xml version='1.0' encoding='us-ascii'?>";
620 XML_Parser ext_parser;
621 XML_ParsingStatus status;
622 enum XML_Status rc;
623
624 UNUSED_P(base);
625 UNUSED_P(systemId);
626 UNUSED_P(publicId);
627 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
628 if (ext_parser == NULL)
629 fail("Could not create external entity parser");
630 XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
631 XML_SetUserData(ext_parser, ext_parser);
632 rc = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
633 XML_GetParsingStatus(ext_parser, &status);
634 if (g_resumable) {
635 if (rc == XML_STATUS_ERROR)
636 xml_failure(ext_parser);
637 if (status.parsing != XML_SUSPENDED)
638 fail("Ext Parsing status not SUSPENDED");
639 } else {
640 if (rc != XML_STATUS_ERROR)
641 fail("Ext parsing not aborted");
642 if (XML_GetErrorCode(ext_parser) != XML_ERROR_ABORTED)
643 xml_failure(ext_parser);
644 if (status.parsing != XML_FINISHED)
645 fail("Ext Parsing status not FINISHED");
646 }
647
648 XML_ParserFree(ext_parser);
649 return XML_STATUS_OK;
650 }
651
652 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)653 external_entity_suspending_faulter(XML_Parser parser, const XML_Char *context,
654 const XML_Char *base,
655 const XML_Char *systemId,
656 const XML_Char *publicId) {
657 XML_Parser ext_parser;
658 ExtFaults *fault = XML_GetUserData(parser);
659 void *buffer;
660 int parse_len = (int)strlen(fault->parse_text);
661
662 UNUSED_P(base);
663 UNUSED_P(systemId);
664 UNUSED_P(publicId);
665 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
666 if (ext_parser == NULL)
667 fail("Could not create external entity parser");
668 XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
669 XML_SetUserData(ext_parser, ext_parser);
670 g_resumable = XML_TRUE;
671 buffer = XML_GetBuffer(ext_parser, parse_len);
672 if (buffer == NULL)
673 fail("Could not allocate parse buffer");
674 assert(buffer != NULL);
675 memcpy(buffer, fault->parse_text, parse_len);
676 if (XML_ParseBuffer(ext_parser, parse_len, XML_FALSE) != XML_STATUS_SUSPENDED)
677 fail("XML declaration did not suspend");
678 if (XML_ResumeParser(ext_parser) != XML_STATUS_OK)
679 xml_failure(ext_parser);
680 if (XML_ParseBuffer(ext_parser, 0, XML_TRUE) != XML_STATUS_ERROR)
681 fail(fault->fail_text);
682 if (XML_GetErrorCode(ext_parser) != fault->error)
683 xml_failure(ext_parser);
684
685 XML_ParserFree(ext_parser);
686 return XML_STATUS_ERROR;
687 }
688
689 int XMLCALL
external_entity_failer__if_not_xml_ge(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)690 external_entity_failer__if_not_xml_ge(XML_Parser parser,
691 const XML_Char *context,
692 const XML_Char *base,
693 const XML_Char *systemId,
694 const XML_Char *publicId) {
695 UNUSED_P(parser);
696 UNUSED_P(context);
697 UNUSED_P(base);
698 UNUSED_P(systemId);
699 UNUSED_P(publicId);
700 #if XML_GE == 0
701 fail(
702 "Function external_entity_suspending_failer was called despite XML_GE==0.");
703 #endif
704 return XML_STATUS_OK;
705 }
706
707 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)708 external_entity_cr_catcher(XML_Parser parser, const XML_Char *context,
709 const XML_Char *base, const XML_Char *systemId,
710 const XML_Char *publicId) {
711 const char *text = "\r";
712 XML_Parser ext_parser;
713
714 UNUSED_P(base);
715 UNUSED_P(systemId);
716 UNUSED_P(publicId);
717 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
718 if (ext_parser == NULL)
719 fail("Could not create external entity parser");
720 XML_SetCharacterDataHandler(ext_parser, cr_cdata_handler);
721 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
722 == XML_STATUS_ERROR)
723 xml_failure(ext_parser);
724 XML_ParserFree(ext_parser);
725 return XML_STATUS_OK;
726 }
727
728 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)729 external_entity_bad_cr_catcher(XML_Parser parser, const XML_Char *context,
730 const XML_Char *base, const XML_Char *systemId,
731 const XML_Char *publicId) {
732 const char *text = "<tag>\r";
733 XML_Parser ext_parser;
734
735 UNUSED_P(base);
736 UNUSED_P(systemId);
737 UNUSED_P(publicId);
738 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
739 if (ext_parser == NULL)
740 fail("Could not create external entity parser");
741 XML_SetCharacterDataHandler(ext_parser, cr_cdata_handler);
742 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
743 == XML_STATUS_OK)
744 fail("Async entity error not caught");
745 if (XML_GetErrorCode(ext_parser) != XML_ERROR_ASYNC_ENTITY)
746 xml_failure(ext_parser);
747 XML_ParserFree(ext_parser);
748 return XML_STATUS_OK;
749 }
750
751 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)752 external_entity_rsqb_catcher(XML_Parser parser, const XML_Char *context,
753 const XML_Char *base, const XML_Char *systemId,
754 const XML_Char *publicId) {
755 const char *text = "<tag>]";
756 XML_Parser ext_parser;
757
758 UNUSED_P(base);
759 UNUSED_P(systemId);
760 UNUSED_P(publicId);
761 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
762 if (ext_parser == NULL)
763 fail("Could not create external entity parser");
764 XML_SetCharacterDataHandler(ext_parser, rsqb_handler);
765 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
766 != XML_STATUS_ERROR)
767 fail("Async entity error not caught");
768 if (XML_GetErrorCode(ext_parser) != XML_ERROR_ASYNC_ENTITY)
769 xml_failure(ext_parser);
770 XML_ParserFree(ext_parser);
771 return XML_STATUS_OK;
772 }
773
774 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)775 external_entity_good_cdata_ascii(XML_Parser parser, const XML_Char *context,
776 const XML_Char *base, const XML_Char *systemId,
777 const XML_Char *publicId) {
778 const char *text = "<a><![CDATA[<greeting>Hello, world!</greeting>]]></a>";
779 const XML_Char *expected = XCS("<greeting>Hello, world!</greeting>");
780 CharData storage;
781 XML_Parser ext_parser;
782
783 UNUSED_P(base);
784 UNUSED_P(systemId);
785 UNUSED_P(publicId);
786 CharData_Init(&storage);
787 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
788 if (ext_parser == NULL)
789 fail("Could not create external entity parser");
790 XML_SetUserData(ext_parser, &storage);
791 XML_SetCharacterDataHandler(ext_parser, accumulate_characters);
792
793 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
794 == XML_STATUS_ERROR)
795 xml_failure(ext_parser);
796 CharData_CheckXMLChars(&storage, expected);
797
798 XML_ParserFree(ext_parser);
799 return XML_STATUS_OK;
800 }
801
802 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)803 external_entity_param_checker(XML_Parser parser, const XML_Char *context,
804 const XML_Char *base, const XML_Char *systemId,
805 const XML_Char *publicId) {
806 const char *text = "<!-- Subordinate parser -->\n"
807 "<!ELEMENT doc (#PCDATA)*>";
808 XML_Parser ext_parser;
809
810 UNUSED_P(base);
811 UNUSED_P(systemId);
812 UNUSED_P(publicId);
813 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
814 if (ext_parser == NULL)
815 fail("Could not create external entity parser");
816 g_handler_data = ext_parser;
817 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
818 == XML_STATUS_ERROR) {
819 xml_failure(parser);
820 return XML_STATUS_ERROR;
821 }
822 g_handler_data = parser;
823 XML_ParserFree(ext_parser);
824 return XML_STATUS_OK;
825 }
826
827 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)828 external_entity_ref_param_checker(XML_Parser parameter, const XML_Char *context,
829 const XML_Char *base,
830 const XML_Char *systemId,
831 const XML_Char *publicId) {
832 const char *text = "<!ELEMENT doc (#PCDATA)*>";
833 XML_Parser ext_parser;
834
835 UNUSED_P(base);
836 UNUSED_P(systemId);
837 UNUSED_P(publicId);
838 if ((void *)parameter != g_handler_data)
839 fail("External entity ref handler parameter not correct");
840
841 /* Here we use the global 'parser' variable */
842 ext_parser = XML_ExternalEntityParserCreate(g_parser, context, NULL);
843 if (ext_parser == NULL)
844 fail("Could not create external entity parser");
845 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
846 == XML_STATUS_ERROR)
847 xml_failure(ext_parser);
848
849 XML_ParserFree(ext_parser);
850 return XML_STATUS_OK;
851 }
852
853 int XMLCALL
external_entity_param(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)854 external_entity_param(XML_Parser parser, const XML_Char *context,
855 const XML_Char *base, const XML_Char *systemId,
856 const XML_Char *publicId) {
857 const char *text1 = "<!ELEMENT doc EMPTY>\n"
858 "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
859 "<!ENTITY % e2 '%e1;'>\n"
860 "%e1;\n";
861 const char *text2 = "<!ELEMENT el EMPTY>\n"
862 "<el/>\n";
863 XML_Parser ext_parser;
864
865 UNUSED_P(base);
866 UNUSED_P(publicId);
867 if (systemId == NULL)
868 return XML_STATUS_OK;
869
870 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
871 if (ext_parser == NULL)
872 fail("Could not create external entity parser");
873
874 if (! xcstrcmp(systemId, XCS("004-1.ent"))) {
875 if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
876 != XML_STATUS_ERROR)
877 fail("Inner DTD with invalid tag not rejected");
878 if (XML_GetErrorCode(ext_parser) != XML_ERROR_EXTERNAL_ENTITY_HANDLING)
879 xml_failure(ext_parser);
880 } else if (! xcstrcmp(systemId, XCS("004-2.ent"))) {
881 if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE)
882 != XML_STATUS_ERROR)
883 fail("Invalid tag in external param not rejected");
884 if (XML_GetErrorCode(ext_parser) != XML_ERROR_SYNTAX)
885 xml_failure(ext_parser);
886 } else {
887 fail("Unknown system ID");
888 }
889
890 XML_ParserFree(ext_parser);
891 return XML_STATUS_ERROR;
892 }
893
894 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)895 external_entity_load_ignore(XML_Parser parser, const XML_Char *context,
896 const XML_Char *base, const XML_Char *systemId,
897 const XML_Char *publicId) {
898 const char *text = "<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>";
899 XML_Parser ext_parser;
900
901 UNUSED_P(base);
902 UNUSED_P(systemId);
903 UNUSED_P(publicId);
904 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
905 if (ext_parser == NULL)
906 fail("Could not create external entity parser");
907 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
908 == XML_STATUS_ERROR)
909 xml_failure(parser);
910
911 XML_ParserFree(ext_parser);
912 return XML_STATUS_OK;
913 }
914
915 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)916 external_entity_load_ignore_utf16(XML_Parser parser, const XML_Char *context,
917 const XML_Char *base,
918 const XML_Char *systemId,
919 const XML_Char *publicId) {
920 const char text[] =
921 /* <![IGNORE[<!ELEMENT e (#PCDATA)*>]]> */
922 "<\0!\0[\0I\0G\0N\0O\0R\0E\0[\0"
923 "<\0!\0E\0L\0E\0M\0E\0N\0T\0 \0e\0 \0"
924 "(\0#\0P\0C\0D\0A\0T\0A\0)\0*\0>\0]\0]\0>\0";
925 XML_Parser ext_parser;
926
927 UNUSED_P(base);
928 UNUSED_P(systemId);
929 UNUSED_P(publicId);
930 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
931 if (ext_parser == NULL)
932 fail("Could not create external entity parser");
933 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)sizeof(text) - 1, XML_TRUE)
934 == XML_STATUS_ERROR)
935 xml_failure(parser);
936
937 XML_ParserFree(ext_parser);
938 return XML_STATUS_OK;
939 }
940
941 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)942 external_entity_load_ignore_utf16_be(XML_Parser parser, const XML_Char *context,
943 const XML_Char *base,
944 const XML_Char *systemId,
945 const XML_Char *publicId) {
946 const char text[] =
947 /* <![IGNORE[<!ELEMENT e (#PCDATA)*>]]> */
948 "\0<\0!\0[\0I\0G\0N\0O\0R\0E\0["
949 "\0<\0!\0E\0L\0E\0M\0E\0N\0T\0 \0e\0 "
950 "\0(\0#\0P\0C\0D\0A\0T\0A\0)\0*\0>\0]\0]\0>";
951 XML_Parser ext_parser;
952
953 UNUSED_P(base);
954 UNUSED_P(systemId);
955 UNUSED_P(publicId);
956 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
957 if (ext_parser == NULL)
958 fail("Could not create external entity parser");
959 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)sizeof(text) - 1, XML_TRUE)
960 == XML_STATUS_ERROR)
961 xml_failure(parser);
962
963 XML_ParserFree(ext_parser);
964 return XML_STATUS_OK;
965 }
966
967 int XMLCALL
external_entity_valuer(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)968 external_entity_valuer(XML_Parser parser, const XML_Char *context,
969 const XML_Char *base, const XML_Char *systemId,
970 const XML_Char *publicId) {
971 const char *text1 = "<!ELEMENT doc EMPTY>\n"
972 "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
973 "<!ENTITY % e2 '%e1;'>\n"
974 "%e1;\n";
975 XML_Parser ext_parser;
976
977 UNUSED_P(base);
978 UNUSED_P(publicId);
979 if (systemId == NULL)
980 return XML_STATUS_OK;
981 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
982 if (ext_parser == NULL)
983 fail("Could not create external entity parser");
984 if (! xcstrcmp(systemId, XCS("004-1.ent"))) {
985 if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
986 == XML_STATUS_ERROR)
987 xml_failure(ext_parser);
988 } else if (! xcstrcmp(systemId, XCS("004-2.ent"))) {
989 ExtFaults *fault = XML_GetUserData(parser);
990 enum XML_Status status;
991 enum XML_Error error;
992
993 status = _XML_Parse_SINGLE_BYTES(ext_parser, fault->parse_text,
994 (int)strlen(fault->parse_text), XML_TRUE);
995 if (fault->error == XML_ERROR_NONE) {
996 if (status == XML_STATUS_ERROR)
997 xml_failure(ext_parser);
998 } else {
999 if (status != XML_STATUS_ERROR)
1000 fail(fault->fail_text);
1001 error = XML_GetErrorCode(ext_parser);
1002 if (error != fault->error
1003 && (fault->error != XML_ERROR_XML_DECL
1004 || error != XML_ERROR_TEXT_DECL))
1005 xml_failure(ext_parser);
1006 }
1007 }
1008
1009 XML_ParserFree(ext_parser);
1010 return XML_STATUS_OK;
1011 }
1012
1013 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)1014 external_entity_not_standalone(XML_Parser parser, const XML_Char *context,
1015 const XML_Char *base, const XML_Char *systemId,
1016 const XML_Char *publicId) {
1017 const char *text1 = "<!ELEMENT doc EMPTY>\n"
1018 "<!ENTITY % e1 SYSTEM 'bar'>\n"
1019 "%e1;\n";
1020 const char *text2 = "<!ATTLIST doc a1 CDATA 'value'>";
1021 XML_Parser ext_parser;
1022
1023 UNUSED_P(base);
1024 UNUSED_P(publicId);
1025 if (systemId == NULL)
1026 return XML_STATUS_OK;
1027 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
1028 if (ext_parser == NULL)
1029 fail("Could not create external entity parser");
1030 if (! xcstrcmp(systemId, XCS("foo"))) {
1031 XML_SetNotStandaloneHandler(ext_parser, reject_not_standalone_handler);
1032 if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
1033 != XML_STATUS_ERROR)
1034 fail("Expected not standalone rejection");
1035 if (XML_GetErrorCode(ext_parser) != XML_ERROR_NOT_STANDALONE)
1036 xml_failure(ext_parser);
1037 XML_SetNotStandaloneHandler(ext_parser, NULL);
1038 XML_ParserFree(ext_parser);
1039 return XML_STATUS_ERROR;
1040 } else if (! xcstrcmp(systemId, XCS("bar"))) {
1041 if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE)
1042 == XML_STATUS_ERROR)
1043 xml_failure(ext_parser);
1044 }
1045
1046 XML_ParserFree(ext_parser);
1047 return XML_STATUS_OK;
1048 }
1049
1050 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)1051 external_entity_value_aborter(XML_Parser parser, const XML_Char *context,
1052 const XML_Char *base, const XML_Char *systemId,
1053 const XML_Char *publicId) {
1054 const char *text1 = "<!ELEMENT doc EMPTY>\n"
1055 "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
1056 "<!ENTITY % e2 '%e1;'>\n"
1057 "%e1;\n";
1058 const char *text2 = "<?xml version='1.0' encoding='utf-8'?>";
1059 XML_Parser ext_parser;
1060
1061 UNUSED_P(base);
1062 UNUSED_P(publicId);
1063 if (systemId == NULL)
1064 return XML_STATUS_OK;
1065 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
1066 if (ext_parser == NULL)
1067 fail("Could not create external entity parser");
1068 if (! xcstrcmp(systemId, XCS("004-1.ent"))) {
1069 if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
1070 == XML_STATUS_ERROR)
1071 xml_failure(ext_parser);
1072 }
1073 if (! xcstrcmp(systemId, XCS("004-2.ent"))) {
1074 XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
1075 XML_SetUserData(ext_parser, ext_parser);
1076 if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE)
1077 != XML_STATUS_ERROR)
1078 fail("Aborted parse not faulted");
1079 if (XML_GetErrorCode(ext_parser) != XML_ERROR_ABORTED)
1080 xml_failure(ext_parser);
1081 }
1082
1083 XML_ParserFree(ext_parser);
1084 return XML_STATUS_OK;
1085 }
1086
1087 int XMLCALL
external_entity_public(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)1088 external_entity_public(XML_Parser parser, const XML_Char *context,
1089 const XML_Char *base, const XML_Char *systemId,
1090 const XML_Char *publicId) {
1091 const char *text1 = XML_GetUserData(parser);
1092 const char *text2 = "<!ATTLIST doc a CDATA 'value'>";
1093 const char *text = NULL;
1094 XML_Parser ext_parser;
1095 int parse_res;
1096
1097 UNUSED_P(base);
1098 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
1099 if (ext_parser == NULL)
1100 return XML_STATUS_ERROR;
1101 if (systemId != NULL && ! xcstrcmp(systemId, XCS("http://example.org/"))) {
1102 text = text1;
1103 } else if (publicId != NULL && ! xcstrcmp(publicId, XCS("foo"))) {
1104 text = text2;
1105 } else
1106 fail("Unexpected parameters to external entity parser");
1107 assert(text != NULL);
1108 parse_res
1109 = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
1110 XML_ParserFree(ext_parser);
1111 return parse_res;
1112 }
1113
1114 int XMLCALL
external_entity_devaluer(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)1115 external_entity_devaluer(XML_Parser parser, const XML_Char *context,
1116 const XML_Char *base, const XML_Char *systemId,
1117 const XML_Char *publicId) {
1118 const char *text = "<!ELEMENT doc EMPTY>\n"
1119 "<!ENTITY % e1 SYSTEM 'bar'>\n"
1120 "%e1;\n";
1121 XML_Parser ext_parser;
1122 int clear_handler_flag = (XML_GetUserData(parser) != NULL);
1123
1124 UNUSED_P(base);
1125 UNUSED_P(publicId);
1126 if (systemId == NULL || ! xcstrcmp(systemId, XCS("bar")))
1127 return XML_STATUS_OK;
1128 if (xcstrcmp(systemId, XCS("foo")) != 0)
1129 fail("Unexpected system ID");
1130 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
1131 if (ext_parser == NULL)
1132 fail("Could note create external entity parser");
1133 if (clear_handler_flag)
1134 XML_SetExternalEntityRefHandler(ext_parser, NULL);
1135 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
1136 == XML_STATUS_ERROR)
1137 xml_failure(ext_parser);
1138
1139 XML_ParserFree(ext_parser);
1140 return XML_STATUS_OK;
1141 }
1142
1143 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)1144 external_entity_oneshot_loader(XML_Parser parser, const XML_Char *context,
1145 const XML_Char *base, const XML_Char *systemId,
1146 const XML_Char *publicId) {
1147 ExtHdlrData *test_data = XML_GetUserData(parser);
1148 XML_Parser ext_parser;
1149
1150 UNUSED_P(base);
1151 UNUSED_P(systemId);
1152 UNUSED_P(publicId);
1153 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
1154 if (ext_parser == NULL)
1155 fail("Could not create external entity parser.");
1156 /* Use the requested entity parser for further externals */
1157 XML_SetExternalEntityRefHandler(ext_parser, test_data->handler);
1158 if (_XML_Parse_SINGLE_BYTES(ext_parser, test_data->parse_text,
1159 (int)strlen(test_data->parse_text), XML_TRUE)
1160 == XML_STATUS_ERROR) {
1161 xml_failure(ext_parser);
1162 }
1163
1164 XML_ParserFree(ext_parser);
1165 return XML_STATUS_OK;
1166 }
1167
1168 int XMLCALL
external_entity_loader2(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)1169 external_entity_loader2(XML_Parser parser, const XML_Char *context,
1170 const XML_Char *base, const XML_Char *systemId,
1171 const XML_Char *publicId) {
1172 ExtTest2 *test_data = XML_GetUserData(parser);
1173 XML_Parser extparser;
1174
1175 UNUSED_P(base);
1176 UNUSED_P(systemId);
1177 UNUSED_P(publicId);
1178 extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
1179 if (extparser == NULL)
1180 fail("Coulr not create external entity parser");
1181 if (test_data->encoding != NULL) {
1182 if (! XML_SetEncoding(extparser, test_data->encoding))
1183 fail("XML_SetEncoding() ignored for external entity");
1184 }
1185 if (_XML_Parse_SINGLE_BYTES(extparser, test_data->parse_text,
1186 test_data->parse_len, XML_TRUE)
1187 == XML_STATUS_ERROR) {
1188 xml_failure(extparser);
1189 }
1190
1191 XML_ParserFree(extparser);
1192 return XML_STATUS_OK;
1193 }
1194
1195 int XMLCALL
external_entity_faulter2(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)1196 external_entity_faulter2(XML_Parser parser, const XML_Char *context,
1197 const XML_Char *base, const XML_Char *systemId,
1198 const XML_Char *publicId) {
1199 ExtFaults2 *test_data = XML_GetUserData(parser);
1200 XML_Parser extparser;
1201
1202 UNUSED_P(base);
1203 UNUSED_P(systemId);
1204 UNUSED_P(publicId);
1205 extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
1206 if (extparser == NULL)
1207 fail("Could not create external entity parser");
1208 if (test_data->encoding != NULL) {
1209 if (! XML_SetEncoding(extparser, test_data->encoding))
1210 fail("XML_SetEncoding() ignored for external entity");
1211 }
1212 if (_XML_Parse_SINGLE_BYTES(extparser, test_data->parse_text,
1213 test_data->parse_len, XML_TRUE)
1214 != XML_STATUS_ERROR)
1215 fail(test_data->fail_text);
1216 if (XML_GetErrorCode(extparser) != test_data->error)
1217 xml_failure(extparser);
1218
1219 XML_ParserFree(extparser);
1220 return XML_STATUS_ERROR;
1221 }
1222
1223 int XMLCALL
external_entity_unfinished_attlist(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)1224 external_entity_unfinished_attlist(XML_Parser parser, const XML_Char *context,
1225 const XML_Char *base,
1226 const XML_Char *systemId,
1227 const XML_Char *publicId) {
1228 const char *text = "<!ELEMENT barf ANY>\n"
1229 "<!ATTLIST barf my_attr (blah|%blah;a|foo) #REQUIRED>\n"
1230 "<!--COMMENT-->\n";
1231 XML_Parser ext_parser;
1232
1233 UNUSED_P(base);
1234 UNUSED_P(publicId);
1235 if (systemId == NULL)
1236 return XML_STATUS_OK;
1237
1238 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
1239 if (ext_parser == NULL)
1240 fail("Could not create external entity parser");
1241
1242 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
1243 == XML_STATUS_ERROR)
1244 xml_failure(ext_parser);
1245
1246 XML_ParserFree(ext_parser);
1247 return XML_STATUS_OK;
1248 }
1249
1250 int XMLCALL
external_entity_handler(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)1251 external_entity_handler(XML_Parser parser, const XML_Char *context,
1252 const XML_Char *base, const XML_Char *systemId,
1253 const XML_Char *publicId) {
1254 void *user_data = XML_GetUserData(parser);
1255 const char *text;
1256 XML_Parser p2;
1257
1258 UNUSED_P(base);
1259 UNUSED_P(systemId);
1260 UNUSED_P(publicId);
1261 if (user_data == NULL)
1262 text = ("<!ELEMENT doc (e+)>\n"
1263 "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
1264 "<!ELEMENT e EMPTY>\n");
1265 else
1266 text = ("<?xml version='1.0' encoding='us-ascii'?>"
1267 "<e/>");
1268
1269 /* Set user data to any non-NULL value */
1270 XML_SetUserData(parser, parser);
1271 p2 = XML_ExternalEntityParserCreate(parser, context, NULL);
1272 if (_XML_Parse_SINGLE_BYTES(p2, text, (int)strlen(text), XML_TRUE)
1273 == XML_STATUS_ERROR) {
1274 xml_failure(p2);
1275 return XML_STATUS_ERROR;
1276 }
1277 XML_ParserFree(p2);
1278 return XML_STATUS_OK;
1279 }
1280
1281 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)1282 external_entity_duff_loader(XML_Parser parser, const XML_Char *context,
1283 const XML_Char *base, const XML_Char *systemId,
1284 const XML_Char *publicId) {
1285 XML_Parser new_parser;
1286 unsigned int i;
1287 const unsigned int max_alloc_count = 10;
1288
1289 UNUSED_P(base);
1290 UNUSED_P(systemId);
1291 UNUSED_P(publicId);
1292 /* Try a few different allocation levels */
1293 for (i = 0; i < max_alloc_count; i++) {
1294 g_allocation_count = (int)i;
1295 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
1296 if (new_parser != NULL) {
1297 XML_ParserFree(new_parser);
1298 break;
1299 }
1300 }
1301 if (i == 0)
1302 fail("External parser creation ignored failing allocator");
1303 else if (i == max_alloc_count)
1304 fail("Extern parser not created with max allocation count");
1305
1306 /* Make sure other random allocation doesn't now fail */
1307 g_allocation_count = ALLOC_ALWAYS_SUCCEED;
1308
1309 /* Make sure the failure code path is executed too */
1310 return XML_STATUS_ERROR;
1311 }
1312
1313 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)1314 external_entity_dbl_handler(XML_Parser parser, const XML_Char *context,
1315 const XML_Char *base, const XML_Char *systemId,
1316 const XML_Char *publicId) {
1317 int *pcallno = XML_GetUserData(parser);
1318 int callno = *pcallno;
1319 const char *text;
1320 XML_Parser new_parser = NULL;
1321 int i;
1322 const int max_alloc_count = 20;
1323
1324 UNUSED_P(base);
1325 UNUSED_P(systemId);
1326 UNUSED_P(publicId);
1327 if (callno == 0) {
1328 /* First time through, check how many calls to malloc occur */
1329 text = ("<!ELEMENT doc (e+)>\n"
1330 "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
1331 "<!ELEMENT e EMPTY>\n");
1332 g_allocation_count = 10000;
1333 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
1334 if (new_parser == NULL) {
1335 fail("Unable to allocate first external parser");
1336 return XML_STATUS_ERROR;
1337 }
1338 /* Stash the number of calls in the user data */
1339 *pcallno = 10000 - g_allocation_count;
1340 } else {
1341 text = ("<?xml version='1.0' encoding='us-ascii'?>"
1342 "<e/>");
1343 /* Try at varying levels to exercise more code paths */
1344 for (i = 0; i < max_alloc_count; i++) {
1345 g_allocation_count = callno + i;
1346 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
1347 if (new_parser != NULL)
1348 break;
1349 }
1350 if (i == 0) {
1351 fail("Second external parser unexpectedly created");
1352 XML_ParserFree(new_parser);
1353 return XML_STATUS_ERROR;
1354 } else if (i == max_alloc_count) {
1355 fail("Second external parser not created");
1356 return XML_STATUS_ERROR;
1357 }
1358 }
1359
1360 g_allocation_count = ALLOC_ALWAYS_SUCCEED;
1361 if (_XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE)
1362 == XML_STATUS_ERROR) {
1363 xml_failure(new_parser);
1364 return XML_STATUS_ERROR;
1365 }
1366 XML_ParserFree(new_parser);
1367 return XML_STATUS_OK;
1368 }
1369
1370 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)1371 external_entity_dbl_handler_2(XML_Parser parser, const XML_Char *context,
1372 const XML_Char *base, const XML_Char *systemId,
1373 const XML_Char *publicId) {
1374 int *pcallno = XML_GetUserData(parser);
1375 int callno = *pcallno;
1376 const char *text;
1377 XML_Parser new_parser;
1378 enum XML_Status rv;
1379
1380 UNUSED_P(base);
1381 UNUSED_P(systemId);
1382 UNUSED_P(publicId);
1383 if (callno == 0) {
1384 /* Try different allocation levels for whole exercise */
1385 text = ("<!ELEMENT doc (e+)>\n"
1386 "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
1387 "<!ELEMENT e EMPTY>\n");
1388 *pcallno = 1;
1389 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
1390 if (new_parser == NULL)
1391 return XML_STATUS_ERROR;
1392 rv = _XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE);
1393 } else {
1394 /* Just run through once */
1395 text = ("<?xml version='1.0' encoding='us-ascii'?>"
1396 "<e/>");
1397 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
1398 if (new_parser == NULL)
1399 return XML_STATUS_ERROR;
1400 rv = _XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE);
1401 }
1402 XML_ParserFree(new_parser);
1403 if (rv == XML_STATUS_ERROR)
1404 return XML_STATUS_ERROR;
1405 return XML_STATUS_OK;
1406 }
1407
1408 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)1409 external_entity_alloc_set_encoding(XML_Parser parser, const XML_Char *context,
1410 const XML_Char *base,
1411 const XML_Char *systemId,
1412 const XML_Char *publicId) {
1413 /* As for external_entity_loader() */
1414 const char *text = "<?xml encoding='iso-8859-3'?>"
1415 "\xC3\xA9";
1416 XML_Parser ext_parser;
1417 enum XML_Status status;
1418
1419 UNUSED_P(base);
1420 UNUSED_P(systemId);
1421 UNUSED_P(publicId);
1422 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
1423 if (ext_parser == NULL)
1424 return XML_STATUS_ERROR;
1425 if (! XML_SetEncoding(ext_parser, XCS("utf-8"))) {
1426 XML_ParserFree(ext_parser);
1427 return XML_STATUS_ERROR;
1428 }
1429 status
1430 = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
1431 XML_ParserFree(ext_parser);
1432 if (status == XML_STATUS_ERROR)
1433 return XML_STATUS_ERROR;
1434 return XML_STATUS_OK;
1435 }
1436
1437 int XMLCALL
external_entity_reallocator(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)1438 external_entity_reallocator(XML_Parser parser, const XML_Char *context,
1439 const XML_Char *base, const XML_Char *systemId,
1440 const XML_Char *publicId) {
1441 const char *text = get_buffer_test_text;
1442 XML_Parser ext_parser;
1443 void *buffer;
1444 enum XML_Status status;
1445
1446 UNUSED_P(base);
1447 UNUSED_P(systemId);
1448 UNUSED_P(publicId);
1449 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
1450 if (ext_parser == NULL)
1451 fail("Could not create external entity parser");
1452
1453 g_reallocation_count = *(int *)XML_GetUserData(parser);
1454 buffer = XML_GetBuffer(ext_parser, 1536);
1455 if (buffer == NULL)
1456 fail("Buffer allocation failed");
1457 assert(buffer != NULL);
1458 memcpy(buffer, text, strlen(text));
1459 status = XML_ParseBuffer(ext_parser, (int)strlen(text), XML_FALSE);
1460 g_reallocation_count = -1;
1461 XML_ParserFree(ext_parser);
1462 return (status == XML_STATUS_OK) ? XML_STATUS_OK : XML_STATUS_ERROR;
1463 }
1464
1465 int XMLCALL
external_entity_alloc(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)1466 external_entity_alloc(XML_Parser parser, const XML_Char *context,
1467 const XML_Char *base, const XML_Char *systemId,
1468 const XML_Char *publicId) {
1469 const char *text = XML_GetUserData(parser);
1470 XML_Parser ext_parser;
1471 int parse_res;
1472
1473 UNUSED_P(base);
1474 UNUSED_P(systemId);
1475 UNUSED_P(publicId);
1476 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
1477 if (ext_parser == NULL)
1478 return XML_STATUS_ERROR;
1479 parse_res
1480 = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
1481 XML_ParserFree(ext_parser);
1482 return parse_res;
1483 }
1484
1485 int XMLCALL
external_entity_parser_create_alloc_fail_handler(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)1486 external_entity_parser_create_alloc_fail_handler(XML_Parser parser,
1487 const XML_Char *context,
1488 const XML_Char *base,
1489 const XML_Char *systemId,
1490 const XML_Char *publicId) {
1491 UNUSED_P(base);
1492 UNUSED_P(systemId);
1493 UNUSED_P(publicId);
1494
1495 if (context != NULL)
1496 fail("Unexpected non-NULL context");
1497
1498 // The following number intends to fail the upcoming allocation in line
1499 // "parser->m_protocolEncodingName = copyString(encodingName,
1500 // &(parser->m_mem));" in function parserInit.
1501 g_allocation_count = 3;
1502
1503 const XML_Char *const encodingName = XCS("UTF-8"); // needs something non-NULL
1504 const XML_Parser ext_parser
1505 = XML_ExternalEntityParserCreate(parser, context, encodingName);
1506 if (ext_parser != NULL)
1507 fail(
1508 "Call to XML_ExternalEntityParserCreate was expected to fail out-of-memory");
1509
1510 g_allocation_count = ALLOC_ALWAYS_SUCCEED;
1511 return XML_STATUS_ERROR;
1512 }
1513
1514 #if XML_GE == 1
1515 int
accounting_external_entity_ref_handler(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)1516 accounting_external_entity_ref_handler(XML_Parser parser,
1517 const XML_Char *context,
1518 const XML_Char *base,
1519 const XML_Char *systemId,
1520 const XML_Char *publicId) {
1521 UNUSED_P(base);
1522 UNUSED_P(publicId);
1523
1524 const struct AccountingTestCase *const testCase = XML_GetUserData(parser);
1525
1526 const char *externalText = NULL;
1527 if (xcstrcmp(systemId, XCS("first.ent")) == 0) {
1528 externalText = testCase->firstExternalText;
1529 } else if (xcstrcmp(systemId, XCS("second.ent")) == 0) {
1530 externalText = testCase->secondExternalText;
1531 } else {
1532 assert(! "systemId is neither \"first.ent\" nor \"second.ent\"");
1533 }
1534 assert(externalText);
1535
1536 XML_Parser entParser = XML_ExternalEntityParserCreate(parser, context, 0);
1537 assert(entParser);
1538
1539 const enum XML_Status status = _XML_Parse_SINGLE_BYTES(
1540 entParser, externalText, (int)strlen(externalText), XML_TRUE);
1541
1542 XML_ParserFree(entParser);
1543 return status;
1544 }
1545 #endif /* XML_GE == 1 */
1546
1547 /* NotStandalone handlers */
1548
1549 int XMLCALL
reject_not_standalone_handler(void * userData)1550 reject_not_standalone_handler(void *userData) {
1551 UNUSED_P(userData);
1552 return XML_STATUS_ERROR;
1553 }
1554
1555 int XMLCALL
accept_not_standalone_handler(void * userData)1556 accept_not_standalone_handler(void *userData) {
1557 UNUSED_P(userData);
1558 return XML_STATUS_OK;
1559 }
1560
1561 /* Attribute List handlers */
1562 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)1563 verify_attlist_decl_handler(void *userData, const XML_Char *element_name,
1564 const XML_Char *attr_name,
1565 const XML_Char *attr_type,
1566 const XML_Char *default_value, int is_required) {
1567 AttTest *at = (AttTest *)userData;
1568
1569 if (xcstrcmp(element_name, at->element_name) != 0)
1570 fail("Unexpected element name in attribute declaration");
1571 if (xcstrcmp(attr_name, at->attr_name) != 0)
1572 fail("Unexpected attribute name in attribute declaration");
1573 if (xcstrcmp(attr_type, at->attr_type) != 0)
1574 fail("Unexpected attribute type in attribute declaration");
1575 if ((default_value == NULL && at->default_value != NULL)
1576 || (default_value != NULL && at->default_value == NULL)
1577 || (default_value != NULL
1578 && xcstrcmp(default_value, at->default_value) != 0))
1579 fail("Unexpected default value in attribute declaration");
1580 if (is_required != at->is_required)
1581 fail("Requirement mismatch in attribute declaration");
1582 }
1583
1584 /* Character Data handlers */
1585
1586 void XMLCALL
clearing_aborting_character_handler(void * userData,const XML_Char * s,int len)1587 clearing_aborting_character_handler(void *userData, const XML_Char *s,
1588 int len) {
1589 UNUSED_P(userData);
1590 UNUSED_P(s);
1591 UNUSED_P(len);
1592 XML_StopParser(g_parser, g_resumable);
1593 XML_SetCharacterDataHandler(g_parser, NULL);
1594 }
1595
1596 void XMLCALL
parser_stop_character_handler(void * userData,const XML_Char * s,int len)1597 parser_stop_character_handler(void *userData, const XML_Char *s, int len) {
1598 UNUSED_P(userData);
1599 UNUSED_P(s);
1600 UNUSED_P(len);
1601 XML_ParsingStatus status;
1602 XML_GetParsingStatus(g_parser, &status);
1603 if (status.parsing == XML_FINISHED) {
1604 return; // the parser was stopped by a previous call to this handler.
1605 }
1606 XML_StopParser(g_parser, g_resumable);
1607 XML_SetCharacterDataHandler(g_parser, NULL);
1608 if (! g_resumable) {
1609 /* Check that aborting an aborted parser is faulted */
1610 if (XML_StopParser(g_parser, XML_FALSE) != XML_STATUS_ERROR)
1611 fail("Aborting aborted parser not faulted");
1612 if (XML_GetErrorCode(g_parser) != XML_ERROR_FINISHED)
1613 xml_failure(g_parser);
1614 } else if (g_abortable) {
1615 /* Check that aborting a suspended parser works */
1616 if (XML_StopParser(g_parser, XML_FALSE) == XML_STATUS_ERROR)
1617 xml_failure(g_parser);
1618 } else {
1619 /* Check that suspending a suspended parser works */
1620 if (XML_StopParser(g_parser, XML_TRUE) != XML_STATUS_ERROR)
1621 fail("Suspending suspended parser not faulted");
1622 if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED)
1623 xml_failure(g_parser);
1624 }
1625 }
1626
1627 void XMLCALL
cr_cdata_handler(void * userData,const XML_Char * s,int len)1628 cr_cdata_handler(void *userData, const XML_Char *s, int len) {
1629 int *pfound = (int *)userData;
1630
1631 /* Internal processing turns the CR into a newline for the
1632 * character data handler, but not for the default handler
1633 */
1634 if (len == 1 && (*s == XCS('\n') || *s == XCS('\r')))
1635 *pfound = 1;
1636 }
1637
1638 void XMLCALL
rsqb_handler(void * userData,const XML_Char * s,int len)1639 rsqb_handler(void *userData, const XML_Char *s, int len) {
1640 int *pfound = (int *)userData;
1641
1642 if (len == 1 && *s == XCS(']'))
1643 *pfound = 1;
1644 }
1645
1646 void XMLCALL
byte_character_handler(void * userData,const XML_Char * s,int len)1647 byte_character_handler(void *userData, const XML_Char *s, int len) {
1648 #if XML_CONTEXT_BYTES > 0
1649 int offset, size;
1650 const char *buffer;
1651 ByteTestData *data = (ByteTestData *)userData;
1652
1653 UNUSED_P(s);
1654 buffer = XML_GetInputContext(g_parser, &offset, &size);
1655 if (buffer == NULL)
1656 fail("Failed to get context buffer");
1657 if (offset != data->start_element_len)
1658 fail("Context offset in unexpected position");
1659 if (len != data->cdata_len)
1660 fail("CDATA length reported incorrectly");
1661 if (size != data->total_string_len)
1662 fail("Context size is not full buffer");
1663 if (XML_GetCurrentByteIndex(g_parser) != offset)
1664 fail("Character byte index incorrect");
1665 if (XML_GetCurrentByteCount(g_parser) != len)
1666 fail("Character byte count incorrect");
1667 #else
1668 UNUSED_P(s);
1669 UNUSED_P(userData);
1670 UNUSED_P(len);
1671 #endif
1672 }
1673
1674 void XMLCALL
ext2_accumulate_characters(void * userData,const XML_Char * s,int len)1675 ext2_accumulate_characters(void *userData, const XML_Char *s, int len) {
1676 ExtTest2 *test_data = (ExtTest2 *)userData;
1677 accumulate_characters(test_data->storage, s, len);
1678 }
1679
1680 /* Handlers that record their function name and int arg. */
1681
1682 static void
record_call(struct handler_record_list * const rec,const char * funcname,const int arg)1683 record_call(struct handler_record_list *const rec, const char *funcname,
1684 const int arg) {
1685 const int max_entries = sizeof(rec->entries) / sizeof(rec->entries[0]);
1686 assert_true(rec->count < max_entries);
1687 struct handler_record_entry *const e = &rec->entries[rec->count++];
1688 e->name = funcname;
1689 e->arg = arg;
1690 }
1691
1692 void XMLCALL
record_default_handler(void * userData,const XML_Char * s,int len)1693 record_default_handler(void *userData, const XML_Char *s, int len) {
1694 UNUSED_P(s);
1695 record_call((struct handler_record_list *)userData, __func__, len);
1696 }
1697
1698 void XMLCALL
record_cdata_handler(void * userData,const XML_Char * s,int len)1699 record_cdata_handler(void *userData, const XML_Char *s, int len) {
1700 UNUSED_P(s);
1701 record_call((struct handler_record_list *)userData, __func__, len);
1702 XML_DefaultCurrent(g_parser);
1703 }
1704
1705 void XMLCALL
record_cdata_nodefault_handler(void * userData,const XML_Char * s,int len)1706 record_cdata_nodefault_handler(void *userData, const XML_Char *s, int len) {
1707 UNUSED_P(s);
1708 record_call((struct handler_record_list *)userData, __func__, len);
1709 }
1710
1711 void XMLCALL
record_skip_handler(void * userData,const XML_Char * entityName,int is_parameter_entity)1712 record_skip_handler(void *userData, const XML_Char *entityName,
1713 int is_parameter_entity) {
1714 UNUSED_P(entityName);
1715 record_call((struct handler_record_list *)userData, __func__,
1716 is_parameter_entity);
1717 }
1718
1719 void XMLCALL
record_element_start_handler(void * userData,const XML_Char * name,const XML_Char ** atts)1720 record_element_start_handler(void *userData, const XML_Char *name,
1721 const XML_Char **atts) {
1722 UNUSED_P(atts);
1723 CharData_AppendXMLChars((CharData *)userData, name, (int)xcstrlen(name));
1724 }
1725
1726 void XMLCALL
record_element_end_handler(void * userData,const XML_Char * name)1727 record_element_end_handler(void *userData, const XML_Char *name) {
1728 CharData *storage = (CharData *)userData;
1729
1730 CharData_AppendXMLChars(storage, XCS("/"), 1);
1731 CharData_AppendXMLChars(storage, name, -1);
1732 }
1733
1734 const struct handler_record_entry *
_handler_record_get(const struct handler_record_list * storage,int index,const char * file,int line)1735 _handler_record_get(const struct handler_record_list *storage, int index,
1736 const char *file, int line) {
1737 if (storage->count <= index) {
1738 _fail(file, line, "too few handler calls");
1739 }
1740 return &storage->entries[index];
1741 }
1742
1743 /* Entity Declaration Handlers */
1744 static const XML_Char *entity_name_to_match = NULL;
1745 static const XML_Char *entity_value_to_match = NULL;
1746 static int entity_match_flag = ENTITY_MATCH_NOT_FOUND;
1747
1748 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)1749 param_entity_match_handler(void *userData, const XML_Char *entityName,
1750 int is_parameter_entity, const XML_Char *value,
1751 int value_length, const XML_Char *base,
1752 const XML_Char *systemId, const XML_Char *publicId,
1753 const XML_Char *notationName) {
1754 UNUSED_P(userData);
1755 UNUSED_P(base);
1756 UNUSED_P(systemId);
1757 UNUSED_P(publicId);
1758 UNUSED_P(notationName);
1759 if (! is_parameter_entity || entity_name_to_match == NULL
1760 || entity_value_to_match == NULL) {
1761 return;
1762 }
1763 if (! xcstrcmp(entityName, entity_name_to_match)) {
1764 /* The cast here is safe because we control the horizontal and
1765 * the vertical, and we therefore know our strings are never
1766 * going to overflow an int.
1767 */
1768 if (value_length != (int)xcstrlen(entity_value_to_match)
1769 || xcstrncmp(value, entity_value_to_match, value_length) != 0) {
1770 entity_match_flag = ENTITY_MATCH_FAIL;
1771 } else {
1772 entity_match_flag = ENTITY_MATCH_SUCCESS;
1773 }
1774 }
1775 /* Else leave the match flag alone */
1776 }
1777
1778 void
param_entity_match_init(const XML_Char * name,const XML_Char * value)1779 param_entity_match_init(const XML_Char *name, const XML_Char *value) {
1780 entity_name_to_match = name;
1781 entity_value_to_match = value;
1782 entity_match_flag = ENTITY_MATCH_NOT_FOUND;
1783 }
1784
1785 int
get_param_entity_match_flag(void)1786 get_param_entity_match_flag(void) {
1787 return entity_match_flag;
1788 }
1789
1790 /* Misc handlers */
1791
1792 void XMLCALL
xml_decl_handler(void * userData,const XML_Char * version,const XML_Char * encoding,int standalone)1793 xml_decl_handler(void *userData, const XML_Char *version,
1794 const XML_Char *encoding, int standalone) {
1795 UNUSED_P(version);
1796 UNUSED_P(encoding);
1797 if (userData != g_handler_data)
1798 fail("User data (xml decl) not correctly set");
1799 if (standalone != -1)
1800 fail("Standalone not flagged as not present in XML decl");
1801 g_xdecl_count++;
1802 }
1803
1804 void XMLCALL
param_check_skip_handler(void * userData,const XML_Char * entityName,int is_parameter_entity)1805 param_check_skip_handler(void *userData, const XML_Char *entityName,
1806 int is_parameter_entity) {
1807 UNUSED_P(entityName);
1808 UNUSED_P(is_parameter_entity);
1809 if (userData != g_handler_data)
1810 fail("User data (skip) not correctly set");
1811 g_skip_count++;
1812 }
1813
1814 void XMLCALL
data_check_comment_handler(void * userData,const XML_Char * data)1815 data_check_comment_handler(void *userData, const XML_Char *data) {
1816 UNUSED_P(data);
1817 /* Check that the userData passed through is what we expect */
1818 if (userData != g_handler_data)
1819 fail("User data (parser) not correctly set");
1820 /* Check that the user data in the parser is appropriate */
1821 if (XML_GetUserData(userData) != (void *)1)
1822 fail("User data in parser not correctly set");
1823 g_comment_count++;
1824 }
1825
1826 void XMLCALL
selective_aborting_default_handler(void * userData,const XML_Char * s,int len)1827 selective_aborting_default_handler(void *userData, const XML_Char *s, int len) {
1828 const XML_Char trigger_char = *(const XML_Char *)userData;
1829
1830 int found = 0;
1831 for (int i = 0; i < len; ++i) {
1832 if (s[i] == trigger_char) {
1833 found = 1;
1834 break;
1835 }
1836 }
1837
1838 if (found) {
1839 XML_StopParser(g_parser, g_resumable);
1840 XML_SetDefaultHandler(g_parser, NULL);
1841 }
1842 }
1843
1844 void XMLCALL
suspending_comment_handler(void * userData,const XML_Char * data)1845 suspending_comment_handler(void *userData, const XML_Char *data) {
1846 UNUSED_P(data);
1847 XML_Parser parser = (XML_Parser)userData;
1848 XML_StopParser(parser, XML_TRUE);
1849 }
1850
1851 void XMLCALL
element_decl_suspender(void * userData,const XML_Char * name,XML_Content * model)1852 element_decl_suspender(void *userData, const XML_Char *name,
1853 XML_Content *model) {
1854 UNUSED_P(userData);
1855 UNUSED_P(name);
1856 XML_StopParser(g_parser, XML_TRUE);
1857 XML_FreeContentModel(g_parser, model);
1858 }
1859
1860 void XMLCALL
suspend_after_element_declaration(void * userData,const XML_Char * name,XML_Content * model)1861 suspend_after_element_declaration(void *userData, const XML_Char *name,
1862 XML_Content *model) {
1863 UNUSED_P(name);
1864 XML_Parser parser = (XML_Parser)userData;
1865 assert_true(XML_StopParser(parser, /*resumable*/ XML_TRUE) == XML_STATUS_OK);
1866 XML_FreeContentModel(parser, model);
1867 }
1868
1869 void XMLCALL
accumulate_pi_characters(void * userData,const XML_Char * target,const XML_Char * data)1870 accumulate_pi_characters(void *userData, const XML_Char *target,
1871 const XML_Char *data) {
1872 CharData *storage = (CharData *)userData;
1873
1874 CharData_AppendXMLChars(storage, target, -1);
1875 CharData_AppendXMLChars(storage, XCS(": "), 2);
1876 CharData_AppendXMLChars(storage, data, -1);
1877 CharData_AppendXMLChars(storage, XCS("\n"), 1);
1878 }
1879
1880 void XMLCALL
accumulate_comment(void * userData,const XML_Char * data)1881 accumulate_comment(void *userData, const XML_Char *data) {
1882 CharData *storage = (CharData *)userData;
1883
1884 CharData_AppendXMLChars(storage, data, -1);
1885 }
1886
1887 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)1888 accumulate_entity_decl(void *userData, const XML_Char *entityName,
1889 int is_parameter_entity, const XML_Char *value,
1890 int value_length, const XML_Char *base,
1891 const XML_Char *systemId, const XML_Char *publicId,
1892 const XML_Char *notationName) {
1893 CharData *storage = (CharData *)userData;
1894
1895 UNUSED_P(is_parameter_entity);
1896 UNUSED_P(base);
1897 UNUSED_P(systemId);
1898 UNUSED_P(publicId);
1899 UNUSED_P(notationName);
1900 CharData_AppendXMLChars(storage, entityName, -1);
1901 CharData_AppendXMLChars(storage, XCS("="), 1);
1902 if (value == NULL)
1903 CharData_AppendXMLChars(storage, XCS("(null)"), -1);
1904 else
1905 CharData_AppendXMLChars(storage, value, value_length);
1906 CharData_AppendXMLChars(storage, XCS("\n"), 1);
1907 }
1908
1909 void XMLCALL
accumulate_char_data_and_suspend(void * userData,const XML_Char * s,int len)1910 accumulate_char_data_and_suspend(void *userData, const XML_Char *s, int len) {
1911 ParserPlusStorage *const parserPlusStorage = (ParserPlusStorage *)userData;
1912
1913 CharData_AppendXMLChars(parserPlusStorage->storage, s, len);
1914
1915 for (int i = 0; i < len; i++) {
1916 if (s[i] == 'Z') {
1917 XML_StopParser(parserPlusStorage->parser, /*resumable=*/XML_TRUE);
1918 break;
1919 }
1920 }
1921 }
1922
1923 void XMLCALL
accumulate_start_element(void * userData,const XML_Char * name,const XML_Char ** atts)1924 accumulate_start_element(void *userData, const XML_Char *name,
1925 const XML_Char **atts) {
1926 CharData *const storage = (CharData *)userData;
1927 CharData_AppendXMLChars(storage, XCS("("), 1);
1928 CharData_AppendXMLChars(storage, name, -1);
1929
1930 if ((atts != NULL) && (atts[0] != NULL)) {
1931 CharData_AppendXMLChars(storage, XCS("("), 1);
1932 while (atts[0] != NULL) {
1933 CharData_AppendXMLChars(storage, atts[0], -1);
1934 CharData_AppendXMLChars(storage, XCS("="), 1);
1935 CharData_AppendXMLChars(storage, atts[1], -1);
1936 atts += 2;
1937 if (atts[0] != NULL) {
1938 CharData_AppendXMLChars(storage, XCS(","), 1);
1939 }
1940 }
1941 CharData_AppendXMLChars(storage, XCS(")"), 1);
1942 }
1943
1944 CharData_AppendXMLChars(storage, XCS(")\n"), 2);
1945 }
1946
1947 void XMLCALL
accumulate_characters(void * userData,const XML_Char * s,int len)1948 accumulate_characters(void *userData, const XML_Char *s, int len) {
1949 CharData *const storage = (CharData *)userData;
1950 CharData_AppendXMLChars(storage, s, len);
1951 }
1952
1953 void XMLCALL
accumulate_attribute(void * userData,const XML_Char * name,const XML_Char ** atts)1954 accumulate_attribute(void *userData, const XML_Char *name,
1955 const XML_Char **atts) {
1956 CharData *const storage = (CharData *)userData;
1957 UNUSED_P(name);
1958 /* Check there are attributes to deal with */
1959 if (atts == NULL)
1960 return;
1961
1962 while (storage->count < 0 && atts[0] != NULL) {
1963 /* "accumulate" the value of the first attribute we see */
1964 CharData_AppendXMLChars(storage, atts[1], -1);
1965 atts += 2;
1966 }
1967 }
1968
1969 void XMLCALL
ext_accumulate_characters(void * userData,const XML_Char * s,int len)1970 ext_accumulate_characters(void *userData, const XML_Char *s, int len) {
1971 ExtTest *const test_data = (ExtTest *)userData;
1972 accumulate_characters(test_data->storage, s, len);
1973 }
1974
1975 void XMLCALL
checking_default_handler(void * userData,const XML_Char * s,int len)1976 checking_default_handler(void *userData, const XML_Char *s, int len) {
1977 DefaultCheck *data = (DefaultCheck *)userData;
1978 int i;
1979
1980 for (i = 0; data[i].expected != NULL; i++) {
1981 if (data[i].expectedLen == len
1982 && ! memcmp(data[i].expected, s, len * sizeof(XML_Char))) {
1983 data[i].seen = XML_TRUE;
1984 break;
1985 }
1986 }
1987 }
1988
1989 void XMLCALL
accumulate_and_suspend_comment_handler(void * userData,const XML_Char * data)1990 accumulate_and_suspend_comment_handler(void *userData, const XML_Char *data) {
1991 ParserPlusStorage *const parserPlusStorage = (ParserPlusStorage *)userData;
1992 accumulate_comment(parserPlusStorage->storage, data);
1993 XML_StopParser(parserPlusStorage->parser, XML_TRUE);
1994 }
1995