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