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