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