1 /* Tests in the "namespace" test case 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-2023 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 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 #include "expat_config.h"
45
46 #include <string.h>
47
48 #include "expat.h"
49 #include "internal.h"
50 #include "minicheck.h"
51 #include "common.h"
52 #include "dummy.h"
53 #include "handlers.h"
54 #include "ns_tests.h"
55
56 static void
namespace_setup(void)57 namespace_setup(void) {
58 g_parser = XML_ParserCreateNS(NULL, XCS(' '));
59 if (g_parser == NULL)
60 fail("Parser not created.");
61 }
62
63 static void
namespace_teardown(void)64 namespace_teardown(void) {
65 basic_teardown();
66 }
67
START_TEST(test_return_ns_triplet)68 START_TEST(test_return_ns_triplet) {
69 const char *text = "<foo:e xmlns:foo='http://example.org/' bar:a='12'\n"
70 " xmlns:bar='http://example.org/'>";
71 const char *epilog = "</foo:e>";
72 const XML_Char *elemstr[]
73 = {XCS("http://example.org/ e foo"), XCS("http://example.org/ a bar")};
74 XML_SetReturnNSTriplet(g_parser, XML_TRUE);
75 XML_SetUserData(g_parser, (void *)elemstr);
76 XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
77 XML_SetNamespaceDeclHandler(g_parser, dummy_start_namespace_decl_handler,
78 dummy_end_namespace_decl_handler);
79 g_triplet_start_flag = XML_FALSE;
80 g_triplet_end_flag = XML_FALSE;
81 init_dummy_handlers();
82 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
83 == XML_STATUS_ERROR)
84 xml_failure(g_parser);
85 /* Check that unsetting "return triplets" fails while still parsing */
86 XML_SetReturnNSTriplet(g_parser, XML_FALSE);
87 if (_XML_Parse_SINGLE_BYTES(g_parser, epilog, (int)strlen(epilog), XML_TRUE)
88 == XML_STATUS_ERROR)
89 xml_failure(g_parser);
90 if (! g_triplet_start_flag)
91 fail("triplet_start_checker not invoked");
92 if (! g_triplet_end_flag)
93 fail("triplet_end_checker not invoked");
94 if (get_dummy_handler_flags()
95 != (DUMMY_START_NS_DECL_HANDLER_FLAG | DUMMY_END_NS_DECL_HANDLER_FLAG))
96 fail("Namespace handlers not called");
97 }
98 END_TEST
99
100 /* Test that the parsing status is correctly reset by XML_ParserReset().
101 * We use test_return_ns_triplet() for our example parse to improve
102 * coverage of tidying up code executed.
103 */
START_TEST(test_ns_parser_reset)104 START_TEST(test_ns_parser_reset) {
105 XML_ParsingStatus status;
106
107 XML_GetParsingStatus(g_parser, &status);
108 if (status.parsing != XML_INITIALIZED)
109 fail("parsing status doesn't start INITIALIZED");
110 test_return_ns_triplet();
111 XML_GetParsingStatus(g_parser, &status);
112 if (status.parsing != XML_FINISHED)
113 fail("parsing status doesn't end FINISHED");
114 XML_ParserReset(g_parser, NULL);
115 XML_GetParsingStatus(g_parser, &status);
116 if (status.parsing != XML_INITIALIZED)
117 fail("parsing status doesn't reset to INITIALIZED");
118 }
119 END_TEST
120
121 static void
run_ns_tagname_overwrite_test(const char * text,const XML_Char * result)122 run_ns_tagname_overwrite_test(const char *text, const XML_Char *result) {
123 CharData storage;
124 CharData_Init(&storage);
125 XML_SetUserData(g_parser, &storage);
126 XML_SetElementHandler(g_parser, overwrite_start_checker,
127 overwrite_end_checker);
128 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
129 == XML_STATUS_ERROR)
130 xml_failure(g_parser);
131 CharData_CheckXMLChars(&storage, result);
132 }
133
134 /* Regression test for SF bug #566334. */
START_TEST(test_ns_tagname_overwrite)135 START_TEST(test_ns_tagname_overwrite) {
136 const char *text = "<n:e xmlns:n='http://example.org/'>\n"
137 " <n:f n:attr='foo'/>\n"
138 " <n:g n:attr2='bar'/>\n"
139 "</n:e>";
140 const XML_Char *result = XCS("start http://example.org/ e\n")
141 XCS("start http://example.org/ f\n")
142 XCS("attribute http://example.org/ attr\n")
143 XCS("end http://example.org/ f\n")
144 XCS("start http://example.org/ g\n")
145 XCS("attribute http://example.org/ attr2\n")
146 XCS("end http://example.org/ g\n")
147 XCS("end http://example.org/ e\n");
148 run_ns_tagname_overwrite_test(text, result);
149 }
150 END_TEST
151
152 /* Regression test for SF bug #566334. */
START_TEST(test_ns_tagname_overwrite_triplet)153 START_TEST(test_ns_tagname_overwrite_triplet) {
154 const char *text = "<n:e xmlns:n='http://example.org/'>\n"
155 " <n:f n:attr='foo'/>\n"
156 " <n:g n:attr2='bar'/>\n"
157 "</n:e>";
158 const XML_Char *result = XCS("start http://example.org/ e n\n")
159 XCS("start http://example.org/ f n\n")
160 XCS("attribute http://example.org/ attr n\n")
161 XCS("end http://example.org/ f n\n")
162 XCS("start http://example.org/ g n\n")
163 XCS("attribute http://example.org/ attr2 n\n")
164 XCS("end http://example.org/ g n\n")
165 XCS("end http://example.org/ e n\n");
166 XML_SetReturnNSTriplet(g_parser, XML_TRUE);
167 run_ns_tagname_overwrite_test(text, result);
168 }
169 END_TEST
170
171 /* Regression test for SF bug #620343. */
START_TEST(test_start_ns_clears_start_element)172 START_TEST(test_start_ns_clears_start_element) {
173 /* This needs to use separate start/end tags; using the empty tag
174 syntax doesn't cause the problematic path through Expat to be
175 taken.
176 */
177 const char *text = "<e xmlns='http://example.org/'></e>";
178
179 XML_SetStartElementHandler(g_parser, start_element_fail);
180 XML_SetStartNamespaceDeclHandler(g_parser, start_ns_clearing_start_element);
181 XML_SetEndNamespaceDeclHandler(g_parser, dummy_end_namespace_decl_handler);
182 XML_UseParserAsHandlerArg(g_parser);
183 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
184 == XML_STATUS_ERROR)
185 xml_failure(g_parser);
186 }
187 END_TEST
188
189 /* Regression test for SF bug #616863. */
START_TEST(test_default_ns_from_ext_subset_and_ext_ge)190 START_TEST(test_default_ns_from_ext_subset_and_ext_ge) {
191 const char *text = "<?xml version='1.0'?>\n"
192 "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n"
193 " <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n"
194 "]>\n"
195 "<doc xmlns='http://example.org/ns1'>\n"
196 "&en;\n"
197 "</doc>";
198
199 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
200 XML_SetExternalEntityRefHandler(g_parser, external_entity_handler);
201 /* We actually need to set this handler to tickle this bug. */
202 XML_SetStartElementHandler(g_parser, dummy_start_element);
203 XML_SetUserData(g_parser, NULL);
204 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
205 == XML_STATUS_ERROR)
206 xml_failure(g_parser);
207 }
208 END_TEST
209
210 /* Regression test #1 for SF bug #673791. */
START_TEST(test_ns_prefix_with_empty_uri_1)211 START_TEST(test_ns_prefix_with_empty_uri_1) {
212 const char *text = "<doc xmlns:prefix='http://example.org/'>\n"
213 " <e xmlns:prefix=''/>\n"
214 "</doc>";
215
216 expect_failure(text, XML_ERROR_UNDECLARING_PREFIX,
217 "Did not report re-setting namespace"
218 " URI with prefix to ''.");
219 }
220 END_TEST
221
222 /* Regression test #2 for SF bug #673791. */
START_TEST(test_ns_prefix_with_empty_uri_2)223 START_TEST(test_ns_prefix_with_empty_uri_2) {
224 const char *text = "<?xml version='1.0'?>\n"
225 "<docelem xmlns:pre=''/>";
226
227 expect_failure(text, XML_ERROR_UNDECLARING_PREFIX,
228 "Did not report setting namespace URI with prefix to ''.");
229 }
230 END_TEST
231
232 /* Regression test #3 for SF bug #673791. */
START_TEST(test_ns_prefix_with_empty_uri_3)233 START_TEST(test_ns_prefix_with_empty_uri_3) {
234 const char *text = "<!DOCTYPE doc [\n"
235 " <!ELEMENT doc EMPTY>\n"
236 " <!ATTLIST doc\n"
237 " xmlns:prefix CDATA ''>\n"
238 "]>\n"
239 "<doc/>";
240
241 expect_failure(text, XML_ERROR_UNDECLARING_PREFIX,
242 "Didn't report attr default setting NS w/ prefix to ''.");
243 }
244 END_TEST
245
246 /* Regression test #4 for SF bug #673791. */
START_TEST(test_ns_prefix_with_empty_uri_4)247 START_TEST(test_ns_prefix_with_empty_uri_4) {
248 const char *text = "<!DOCTYPE doc [\n"
249 " <!ELEMENT prefix:doc EMPTY>\n"
250 " <!ATTLIST prefix:doc\n"
251 " xmlns:prefix CDATA 'http://example.org/'>\n"
252 "]>\n"
253 "<prefix:doc/>";
254 /* Packaged info expected by the end element handler;
255 the weird structuring lets us reuse the triplet_end_checker()
256 function also used for another test. */
257 const XML_Char *elemstr[] = {XCS("http://example.org/ doc prefix")};
258 XML_SetReturnNSTriplet(g_parser, XML_TRUE);
259 XML_SetUserData(g_parser, (void *)elemstr);
260 XML_SetEndElementHandler(g_parser, triplet_end_checker);
261 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
262 == XML_STATUS_ERROR)
263 xml_failure(g_parser);
264 }
265 END_TEST
266
267 /* Test with non-xmlns prefix */
START_TEST(test_ns_unbound_prefix)268 START_TEST(test_ns_unbound_prefix) {
269 const char *text = "<!DOCTYPE doc [\n"
270 " <!ELEMENT prefix:doc EMPTY>\n"
271 " <!ATTLIST prefix:doc\n"
272 " notxmlns:prefix CDATA 'http://example.org/'>\n"
273 "]>\n"
274 "<prefix:doc/>";
275
276 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
277 != XML_STATUS_ERROR)
278 fail("Unbound prefix incorrectly passed");
279 if (XML_GetErrorCode(g_parser) != XML_ERROR_UNBOUND_PREFIX)
280 xml_failure(g_parser);
281 }
282 END_TEST
283
START_TEST(test_ns_default_with_empty_uri)284 START_TEST(test_ns_default_with_empty_uri) {
285 const char *text = "<doc xmlns='http://example.org/'>\n"
286 " <e xmlns=''/>\n"
287 "</doc>";
288 /* Add some handlers to exercise extra code paths */
289 XML_SetStartNamespaceDeclHandler(g_parser,
290 dummy_start_namespace_decl_handler);
291 XML_SetEndNamespaceDeclHandler(g_parser, dummy_end_namespace_decl_handler);
292 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
293 == XML_STATUS_ERROR)
294 xml_failure(g_parser);
295 }
296 END_TEST
297
298 /* Regression test for SF bug #692964: two prefixes for one namespace. */
START_TEST(test_ns_duplicate_attrs_diff_prefixes)299 START_TEST(test_ns_duplicate_attrs_diff_prefixes) {
300 const char *text = "<doc xmlns:a='http://example.org/a'\n"
301 " xmlns:b='http://example.org/a'\n"
302 " a:a='v' b:a='v' />";
303 expect_failure(text, XML_ERROR_DUPLICATE_ATTRIBUTE,
304 "did not report multiple attributes with same URI+name");
305 }
306 END_TEST
307
START_TEST(test_ns_duplicate_hashes)308 START_TEST(test_ns_duplicate_hashes) {
309 /* The hash of an attribute is calculated as the hash of its URI
310 * concatenated with a space followed by its name (after the
311 * colon). We wish to generate attributes with the same hash
312 * value modulo the attribute table size so that we can check that
313 * the attribute hash table works correctly. The attribute hash
314 * table size will be the smallest power of two greater than the
315 * number of attributes, but at least eight. There is
316 * unfortunately no programmatic way of getting the hash or the
317 * table size at user level, but the test code coverage percentage
318 * will drop if the hashes cease to point to the same row.
319 *
320 * The cunning plan is to have few enough attributes to have a
321 * reliable table size of 8, and have the single letter attribute
322 * names be 8 characters apart, producing a hash which will be the
323 * same modulo 8.
324 */
325 const char *text = "<doc xmlns:a='http://example.org/a'\n"
326 " a:a='v' a:i='w' />";
327 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
328 == XML_STATUS_ERROR)
329 xml_failure(g_parser);
330 }
331 END_TEST
332
333 /* Regression test for SF bug #695401: unbound prefix. */
START_TEST(test_ns_unbound_prefix_on_attribute)334 START_TEST(test_ns_unbound_prefix_on_attribute) {
335 const char *text = "<doc a:attr=''/>";
336 expect_failure(text, XML_ERROR_UNBOUND_PREFIX,
337 "did not report unbound prefix on attribute");
338 }
339 END_TEST
340
341 /* Regression test for SF bug #695401: unbound prefix. */
START_TEST(test_ns_unbound_prefix_on_element)342 START_TEST(test_ns_unbound_prefix_on_element) {
343 const char *text = "<a:doc/>";
344 expect_failure(text, XML_ERROR_UNBOUND_PREFIX,
345 "did not report unbound prefix on element");
346 }
347 END_TEST
348
349 /* Test that long element names with namespaces are handled correctly */
START_TEST(test_ns_long_element)350 START_TEST(test_ns_long_element) {
351 const char *text
352 = "<foo:thisisalongenoughelementnametotriggerareallocation\n"
353 " xmlns:foo='http://example.org/' bar:a='12'\n"
354 " xmlns:bar='http://example.org/'>"
355 "</foo:thisisalongenoughelementnametotriggerareallocation>";
356 const XML_Char *elemstr[]
357 = {XCS("http://example.org/")
358 XCS(" thisisalongenoughelementnametotriggerareallocation foo"),
359 XCS("http://example.org/ a bar")};
360
361 XML_SetReturnNSTriplet(g_parser, XML_TRUE);
362 XML_SetUserData(g_parser, (void *)elemstr);
363 XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
364 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
365 == XML_STATUS_ERROR)
366 xml_failure(g_parser);
367 }
368 END_TEST
369
370 /* Test mixed population of prefixed and unprefixed attributes */
START_TEST(test_ns_mixed_prefix_atts)371 START_TEST(test_ns_mixed_prefix_atts) {
372 const char *text = "<e a='12' bar:b='13'\n"
373 " xmlns:bar='http://example.org/'>"
374 "</e>";
375
376 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
377 == XML_STATUS_ERROR)
378 xml_failure(g_parser);
379 }
380 END_TEST
381
382 /* Test having a long namespaced element name inside a short one.
383 * This exercises some internal buffer reallocation that is shared
384 * across elements with the same namespace URI.
385 */
START_TEST(test_ns_extend_uri_buffer)386 START_TEST(test_ns_extend_uri_buffer) {
387 const char *text = "<foo:e xmlns:foo='http://example.org/'>"
388 " <foo:thisisalongenoughnametotriggerallocationaction"
389 " foo:a='12' />"
390 "</foo:e>";
391 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
392 == XML_STATUS_ERROR)
393 xml_failure(g_parser);
394 }
395 END_TEST
396
397 /* Test that xmlns is correctly rejected as an attribute in the xmlns
398 * namespace, but not in other namespaces
399 */
START_TEST(test_ns_reserved_attributes)400 START_TEST(test_ns_reserved_attributes) {
401 const char *text1
402 = "<foo:e xmlns:foo='http://example.org/' xmlns:xmlns='12' />";
403 const char *text2
404 = "<foo:e xmlns:foo='http://example.org/' foo:xmlns='12' />";
405 expect_failure(text1, XML_ERROR_RESERVED_PREFIX_XMLNS,
406 "xmlns not rejected as an attribute");
407 XML_ParserReset(g_parser, NULL);
408 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
409 == XML_STATUS_ERROR)
410 xml_failure(g_parser);
411 }
412 END_TEST
413
414 /* Test more reserved attributes */
START_TEST(test_ns_reserved_attributes_2)415 START_TEST(test_ns_reserved_attributes_2) {
416 const char *text1 = "<foo:e xmlns:foo='http://example.org/'"
417 " xmlns:xml='http://example.org/' />";
418 const char *text2
419 = "<foo:e xmlns:foo='http://www.w3.org/XML/1998/namespace' />";
420 const char *text3 = "<foo:e xmlns:foo='http://www.w3.org/2000/xmlns/' />";
421
422 expect_failure(text1, XML_ERROR_RESERVED_PREFIX_XML,
423 "xml not rejected as an attribute");
424 XML_ParserReset(g_parser, NULL);
425 expect_failure(text2, XML_ERROR_RESERVED_NAMESPACE_URI,
426 "Use of w3.org URL not faulted");
427 XML_ParserReset(g_parser, NULL);
428 expect_failure(text3, XML_ERROR_RESERVED_NAMESPACE_URI,
429 "Use of w3.org xmlns URL not faulted");
430 }
431 END_TEST
432
433 /* Test string pool handling of namespace names of 2048 characters */
434 /* Exercises a particular string pool growth path */
START_TEST(test_ns_extremely_long_prefix)435 START_TEST(test_ns_extremely_long_prefix) {
436 /* C99 compilers are only required to support 4095-character
437 * strings, so the following needs to be split in two to be safe
438 * for all compilers.
439 */
440 const char *text1
441 = "<doc "
442 /* 64 character on each line */
443 /* ...gives a total length of 2048 */
444 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
445 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
446 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
447 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
448 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
449 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
450 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
451 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
452 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
453 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
454 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
455 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
456 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
457 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
458 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
459 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
460 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
461 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
462 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
463 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
464 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
465 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
466 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
467 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
468 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
469 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
470 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
471 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
472 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
473 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
474 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
475 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
476 ":a='12'";
477 const char *text2
478 = " xmlns:"
479 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
480 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
481 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
482 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
483 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
484 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
485 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
486 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
487 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
488 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
489 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
490 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
491 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
492 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
493 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
494 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
495 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
496 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
497 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
498 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
499 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
500 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
501 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
502 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
503 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
504 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
505 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
506 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
507 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
508 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
509 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
510 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
511 "='foo'\n>"
512 "</doc>";
513
514 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
515 == XML_STATUS_ERROR)
516 xml_failure(g_parser);
517 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
518 == XML_STATUS_ERROR)
519 xml_failure(g_parser);
520 }
521 END_TEST
522
523 /* Test unknown encoding handlers in namespace setup */
START_TEST(test_ns_unknown_encoding_success)524 START_TEST(test_ns_unknown_encoding_success) {
525 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
526 "<foo:e xmlns:foo='http://example.org/'>Hi</foo:e>";
527
528 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
529 run_character_check(text, XCS("Hi"));
530 }
531 END_TEST
532
533 /* Test that too many colons are rejected */
START_TEST(test_ns_double_colon)534 START_TEST(test_ns_double_colon) {
535 const char *text = "<foo:e xmlns:foo='http://example.org/' foo:a:b='bar' />";
536 const enum XML_Status status
537 = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE);
538 #ifdef XML_NS
539 if ((status == XML_STATUS_OK)
540 || (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)) {
541 fail("Double colon in attribute name not faulted"
542 " (despite active namespace support)");
543 }
544 #else
545 if (status != XML_STATUS_OK) {
546 fail("Double colon in attribute name faulted"
547 " (despite inactive namespace support");
548 }
549 #endif
550 }
551 END_TEST
552
START_TEST(test_ns_double_colon_element)553 START_TEST(test_ns_double_colon_element) {
554 const char *text = "<foo:bar:e xmlns:foo='http://example.org/' />";
555 const enum XML_Status status
556 = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE);
557 #ifdef XML_NS
558 if ((status == XML_STATUS_OK)
559 || (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)) {
560 fail("Double colon in element name not faulted"
561 " (despite active namespace support)");
562 }
563 #else
564 if (status != XML_STATUS_OK) {
565 fail("Double colon in element name faulted"
566 " (despite inactive namespace support");
567 }
568 #endif
569 }
570 END_TEST
571
572 /* Test that non-name characters after a colon are rejected */
START_TEST(test_ns_bad_attr_leafname)573 START_TEST(test_ns_bad_attr_leafname) {
574 const char *text = "<foo:e xmlns:foo='http://example.org/' foo:?ar='baz' />";
575
576 expect_failure(text, XML_ERROR_INVALID_TOKEN,
577 "Invalid character in leafname not faulted");
578 }
579 END_TEST
580
START_TEST(test_ns_bad_element_leafname)581 START_TEST(test_ns_bad_element_leafname) {
582 const char *text = "<foo:?oc xmlns:foo='http://example.org/' />";
583
584 expect_failure(text, XML_ERROR_INVALID_TOKEN,
585 "Invalid character in element leafname not faulted");
586 }
587 END_TEST
588
589 /* Test high-byte-set UTF-16 characters are valid in a leafname */
START_TEST(test_ns_utf16_leafname)590 START_TEST(test_ns_utf16_leafname) {
591 const char text[] =
592 /* <n:e xmlns:n='URI' n:{KHO KHWAI}='a' />
593 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
594 */
595 "<\0n\0:\0e\0 \0x\0m\0l\0n\0s\0:\0n\0=\0'\0U\0R\0I\0'\0 \0"
596 "n\0:\0\x04\x0e=\0'\0a\0'\0 \0/\0>\0";
597 const XML_Char *expected = XCS("a");
598 CharData storage;
599
600 CharData_Init(&storage);
601 XML_SetStartElementHandler(g_parser, accumulate_attribute);
602 XML_SetUserData(g_parser, &storage);
603 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
604 == XML_STATUS_ERROR)
605 xml_failure(g_parser);
606 CharData_CheckXMLChars(&storage, expected);
607 }
608 END_TEST
609
START_TEST(test_ns_utf16_element_leafname)610 START_TEST(test_ns_utf16_element_leafname) {
611 const char text[] =
612 /* <n:{KHO KHWAI} xmlns:n='URI'/>
613 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
614 */
615 "\0<\0n\0:\x0e\x04\0 \0x\0m\0l\0n\0s\0:\0n\0=\0'\0U\0R\0I\0'\0/\0>";
616 #ifdef XML_UNICODE
617 const XML_Char *expected = XCS("URI \x0e04");
618 #else
619 const XML_Char *expected = XCS("URI \xe0\xb8\x84");
620 #endif
621 CharData storage;
622
623 CharData_Init(&storage);
624 XML_SetStartElementHandler(g_parser, start_element_event_handler);
625 XML_SetUserData(g_parser, &storage);
626 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
627 == XML_STATUS_ERROR)
628 xml_failure(g_parser);
629 CharData_CheckXMLChars(&storage, expected);
630 }
631 END_TEST
632
START_TEST(test_ns_utf16_doctype)633 START_TEST(test_ns_utf16_doctype) {
634 const char text[] =
635 /* <!DOCTYPE foo:{KHO KHWAI} [ <!ENTITY bar 'baz'> ]>\n
636 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
637 */
638 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0f\0o\0o\0:\x0e\x04\0 "
639 "\0[\0 \0<\0!\0E\0N\0T\0I\0T\0Y\0 \0b\0a\0r\0 \0'\0b\0a\0z\0'\0>\0 "
640 "\0]\0>\0\n"
641 /* <foo:{KHO KHWAI} xmlns:foo='URI'>&bar;</foo:{KHO KHWAI}> */
642 "\0<\0f\0o\0o\0:\x0e\x04\0 "
643 "\0x\0m\0l\0n\0s\0:\0f\0o\0o\0=\0'\0U\0R\0I\0'\0>"
644 "\0&\0b\0a\0r\0;"
645 "\0<\0/\0f\0o\0o\0:\x0e\x04\0>";
646 #ifdef XML_UNICODE
647 const XML_Char *expected = XCS("URI \x0e04");
648 #else
649 const XML_Char *expected = XCS("URI \xe0\xb8\x84");
650 #endif
651 CharData storage;
652
653 CharData_Init(&storage);
654 XML_SetUserData(g_parser, &storage);
655 XML_SetStartElementHandler(g_parser, start_element_event_handler);
656 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
657 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
658 == XML_STATUS_ERROR)
659 xml_failure(g_parser);
660 CharData_CheckXMLChars(&storage, expected);
661 }
662 END_TEST
663
START_TEST(test_ns_invalid_doctype)664 START_TEST(test_ns_invalid_doctype) {
665 const char *text = "<!DOCTYPE foo:!bad [ <!ENTITY bar 'baz' ]>\n"
666 "<foo:!bad>&bar;</foo:!bad>";
667
668 expect_failure(text, XML_ERROR_INVALID_TOKEN,
669 "Invalid character in document local name not faulted");
670 }
671 END_TEST
672
START_TEST(test_ns_double_colon_doctype)673 START_TEST(test_ns_double_colon_doctype) {
674 const char *text = "<!DOCTYPE foo:a:doc [ <!ENTITY bar 'baz' ]>\n"
675 "<foo:a:doc>&bar;</foo:a:doc>";
676
677 expect_failure(text, XML_ERROR_SYNTAX,
678 "Double colon in document name not faulted");
679 }
680 END_TEST
681
START_TEST(test_ns_separator_in_uri)682 START_TEST(test_ns_separator_in_uri) {
683 struct test_case {
684 enum XML_Status expectedStatus;
685 const char *doc;
686 XML_Char namesep;
687 };
688 struct test_case cases[] = {
689 {XML_STATUS_OK, "<doc xmlns='one_two' />", XCS('\n')},
690 {XML_STATUS_ERROR, "<doc xmlns='one
two' />", XCS('\n')},
691 {XML_STATUS_OK, "<doc xmlns='one:two' />", XCS(':')},
692 };
693
694 size_t i = 0;
695 size_t failCount = 0;
696 for (; i < sizeof(cases) / sizeof(cases[0]); i++) {
697 set_subtest("%s", cases[i].doc);
698 XML_Parser parser = XML_ParserCreateNS(NULL, cases[i].namesep);
699 XML_SetElementHandler(parser, dummy_start_element, dummy_end_element);
700 if (_XML_Parse_SINGLE_BYTES(parser, cases[i].doc, (int)strlen(cases[i].doc),
701 /*isFinal*/ XML_TRUE)
702 != cases[i].expectedStatus) {
703 failCount++;
704 }
705 XML_ParserFree(parser);
706 }
707
708 if (failCount) {
709 fail("Namespace separator handling is broken");
710 }
711 }
712 END_TEST
713
714 void
make_namespace_test_case(Suite * s)715 make_namespace_test_case(Suite *s) {
716 TCase *tc_namespace = tcase_create("XML namespaces");
717
718 suite_add_tcase(s, tc_namespace);
719 tcase_add_checked_fixture(tc_namespace, namespace_setup, namespace_teardown);
720 tcase_add_test(tc_namespace, test_return_ns_triplet);
721 tcase_add_test(tc_namespace, test_ns_parser_reset);
722 tcase_add_test(tc_namespace, test_ns_tagname_overwrite);
723 tcase_add_test(tc_namespace, test_ns_tagname_overwrite_triplet);
724 tcase_add_test(tc_namespace, test_start_ns_clears_start_element);
725 tcase_add_test__ifdef_xml_dtd(tc_namespace,
726 test_default_ns_from_ext_subset_and_ext_ge);
727 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_1);
728 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_2);
729 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_3);
730 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_4);
731 tcase_add_test(tc_namespace, test_ns_unbound_prefix);
732 tcase_add_test(tc_namespace, test_ns_default_with_empty_uri);
733 tcase_add_test(tc_namespace, test_ns_duplicate_attrs_diff_prefixes);
734 tcase_add_test(tc_namespace, test_ns_duplicate_hashes);
735 tcase_add_test(tc_namespace, test_ns_unbound_prefix_on_attribute);
736 tcase_add_test(tc_namespace, test_ns_unbound_prefix_on_element);
737 tcase_add_test(tc_namespace, test_ns_long_element);
738 tcase_add_test(tc_namespace, test_ns_mixed_prefix_atts);
739 tcase_add_test(tc_namespace, test_ns_extend_uri_buffer);
740 tcase_add_test(tc_namespace, test_ns_reserved_attributes);
741 tcase_add_test(tc_namespace, test_ns_reserved_attributes_2);
742 tcase_add_test(tc_namespace, test_ns_extremely_long_prefix);
743 tcase_add_test(tc_namespace, test_ns_unknown_encoding_success);
744 tcase_add_test(tc_namespace, test_ns_double_colon);
745 tcase_add_test(tc_namespace, test_ns_double_colon_element);
746 tcase_add_test(tc_namespace, test_ns_bad_attr_leafname);
747 tcase_add_test(tc_namespace, test_ns_bad_element_leafname);
748 tcase_add_test(tc_namespace, test_ns_utf16_leafname);
749 tcase_add_test(tc_namespace, test_ns_utf16_element_leafname);
750 tcase_add_test__if_xml_ge(tc_namespace, test_ns_utf16_doctype);
751 tcase_add_test(tc_namespace, test_ns_invalid_doctype);
752 tcase_add_test(tc_namespace, test_ns_double_colon_doctype);
753 tcase_add_test(tc_namespace, test_ns_separator_in_uri);
754 }
755