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