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