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