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