Home | History | Annotate | Line # | Download | only in tests
common.c revision 1.1.1.2.4.2
      1 /* Commonly used functions for the Expat test suite
      2                             __  __            _
      3                          ___\ \/ /_ __   __ _| |_
      4                         / _ \\  /| '_ \ / _` | __|
      5                        |  __//  \| |_) | (_| | |_
      6                         \___/_/\_\ .__/ \__,_|\__|
      7                                  |_| XML parser
      8 
      9    Copyright (c) 2001-2006 Fred L. Drake, Jr. <fdrake (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-2025 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-2024 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 <assert.h>
     45 #include <errno.h>
     46 #include <stdint.h> // for SIZE_MAX
     47 #include <stdio.h>
     48 #include <string.h>
     49 
     50 #include "expat_config.h"
     51 #include "expat.h"
     52 #include "internal.h"
     53 #include "chardata.h"
     54 #include "minicheck.h"
     55 #include "common.h"
     56 #include "handlers.h"
     57 
     58 /* Common test data */
     59 
     60 const char *long_character_data_text
     61     = "<?xml version='1.0' encoding='iso-8859-1'?><s>"
     62       "012345678901234567890123456789012345678901234567890123456789"
     63       "012345678901234567890123456789012345678901234567890123456789"
     64       "012345678901234567890123456789012345678901234567890123456789"
     65       "012345678901234567890123456789012345678901234567890123456789"
     66       "012345678901234567890123456789012345678901234567890123456789"
     67       "012345678901234567890123456789012345678901234567890123456789"
     68       "012345678901234567890123456789012345678901234567890123456789"
     69       "012345678901234567890123456789012345678901234567890123456789"
     70       "012345678901234567890123456789012345678901234567890123456789"
     71       "012345678901234567890123456789012345678901234567890123456789"
     72       "012345678901234567890123456789012345678901234567890123456789"
     73       "012345678901234567890123456789012345678901234567890123456789"
     74       "012345678901234567890123456789012345678901234567890123456789"
     75       "012345678901234567890123456789012345678901234567890123456789"
     76       "012345678901234567890123456789012345678901234567890123456789"
     77       "012345678901234567890123456789012345678901234567890123456789"
     78       "012345678901234567890123456789012345678901234567890123456789"
     79       "012345678901234567890123456789012345678901234567890123456789"
     80       "012345678901234567890123456789012345678901234567890123456789"
     81       "012345678901234567890123456789012345678901234567890123456789"
     82       "</s>";
     83 
     84 const char *long_cdata_text
     85     = "<s><![CDATA["
     86       "012345678901234567890123456789012345678901234567890123456789"
     87       "012345678901234567890123456789012345678901234567890123456789"
     88       "012345678901234567890123456789012345678901234567890123456789"
     89       "012345678901234567890123456789012345678901234567890123456789"
     90       "012345678901234567890123456789012345678901234567890123456789"
     91       "012345678901234567890123456789012345678901234567890123456789"
     92       "012345678901234567890123456789012345678901234567890123456789"
     93       "012345678901234567890123456789012345678901234567890123456789"
     94       "012345678901234567890123456789012345678901234567890123456789"
     95       "012345678901234567890123456789012345678901234567890123456789"
     96       "012345678901234567890123456789012345678901234567890123456789"
     97       "012345678901234567890123456789012345678901234567890123456789"
     98       "012345678901234567890123456789012345678901234567890123456789"
     99       "012345678901234567890123456789012345678901234567890123456789"
    100       "012345678901234567890123456789012345678901234567890123456789"
    101       "012345678901234567890123456789012345678901234567890123456789"
    102       "012345678901234567890123456789012345678901234567890123456789"
    103       "012345678901234567890123456789012345678901234567890123456789"
    104       "012345678901234567890123456789012345678901234567890123456789"
    105       "012345678901234567890123456789012345678901234567890123456789"
    106       "]]></s>";
    107 
    108 /* Having an element name longer than 1024 characters exercises some
    109  * of the pool allocation code in the parser that otherwise does not
    110  * get executed.  The count at the end of the line is the number of
    111  * characters (bytes) in the element name by that point.x
    112  */
    113 const char *get_buffer_test_text
    114     = "<documentwitharidiculouslylongelementnametotease"  /* 0x030 */
    115       "aparticularcorneroftheallocationinXML_GetBuffers"  /* 0x060 */
    116       "othatwecanimprovethecoverageyetagain012345678901"  /* 0x090 */
    117       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x0c0 */
    118       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x0f0 */
    119       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x120 */
    120       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x150 */
    121       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x180 */
    122       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x1b0 */
    123       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x1e0 */
    124       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x210 */
    125       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x240 */
    126       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x270 */
    127       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x2a0 */
    128       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x2d0 */
    129       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x300 */
    130       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x330 */
    131       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x360 */
    132       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x390 */
    133       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x3c0 */
    134       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x3f0 */
    135       "123456789abcdef0123456789abcdef0123456789>\n<ef0"; /* 0x420 */
    136 
    137 /* Test control globals */
    138 
    139 /* Used as the "resumable" parameter to XML_StopParser by some tests */
    140 XML_Bool g_resumable = XML_FALSE;
    141 
    142 /* Used to control abort checks in some tests */
    143 XML_Bool g_abortable = XML_FALSE;
    144 
    145 /* Used to control _XML_Parse_SINGLE_BYTES() chunk size */
    146 int g_chunkSize = 1;
    147 
    148 /* Common test functions */
    149 
    150 void
    151 tcase_add_test__ifdef_xml_dtd(TCase *tc, tcase_test_function test) {
    152 #ifdef XML_DTD
    153   tcase_add_test(tc, test);
    154 #else
    155   UNUSED_P(tc);
    156   UNUSED_P(test);
    157 #endif
    158 }
    159 
    160 void
    161 tcase_add_test__if_xml_ge(TCase *tc, tcase_test_function test) {
    162 #if XML_GE == 1
    163   tcase_add_test(tc, test);
    164 #else
    165   UNUSED_P(tc);
    166   UNUSED_P(test);
    167 #endif
    168 }
    169 
    170 void
    171 basic_teardown(void) {
    172   if (g_parser != NULL) {
    173     XML_ParserFree(g_parser);
    174     g_parser = NULL;
    175   }
    176 }
    177 
    178 /* Generate a failure using the parser state to create an error message;
    179    this should be used when the parser reports an error we weren't
    180    expecting.
    181 */
    182 void
    183 _xml_failure(XML_Parser parser, const char *file, int line) {
    184   char buffer[1024];
    185   enum XML_Error err = XML_GetErrorCode(parser);
    186   snprintf(buffer, sizeof(buffer),
    187            "    %d: %" XML_FMT_STR " (line %" XML_FMT_INT_MOD
    188            "u, offset %" XML_FMT_INT_MOD "u)\n    reported from %s, line %d\n",
    189            err, XML_ErrorString(err), XML_GetCurrentLineNumber(parser),
    190            XML_GetCurrentColumnNumber(parser), file, line);
    191   _fail(file, line, buffer);
    192 }
    193 
    194 enum XML_Status
    195 _XML_Parse_SINGLE_BYTES(XML_Parser parser, const char *s, int len,
    196                         int isFinal) {
    197   // This ensures that tests have to run pathological parse cases
    198   // (e.g. when `s` is NULL) against plain XML_Parse rather than
    199   // chunking _XML_Parse_SINGLE_BYTES.
    200   assert((parser != NULL) && (s != NULL) && (len >= 0));
    201   const int chunksize = g_chunkSize;
    202   if (chunksize > 0) {
    203     // parse in chunks of `chunksize` bytes as long as not exhausting
    204     for (; len > chunksize; len -= chunksize, s += chunksize) {
    205       enum XML_Status res = XML_Parse(parser, s, chunksize, XML_FALSE);
    206       if (res != XML_STATUS_OK) {
    207         if ((res == XML_STATUS_SUSPENDED) && (len > chunksize)) {
    208           fail("Use of function _XML_Parse_SINGLE_BYTES with a chunk size "
    209                "greater than 0 (from g_chunkSize) does not work well with "
    210                "suspension. Please consider use of plain XML_Parse at this "
    211                "place in your test, instead.");
    212         }
    213         return res;
    214       }
    215     }
    216   }
    217   // parse the final chunk, the size of which will be <= chunksize
    218   return XML_Parse(parser, s, len, isFinal);
    219 }
    220 
    221 void
    222 _expect_failure(const char *text, enum XML_Error errorCode,
    223                 const char *errorMessage, const char *file, int lineno) {
    224   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
    225       == XML_STATUS_OK)
    226     /* Hackish use of _fail() macro, but lets us report
    227        the right filename and line number. */
    228     _fail(file, lineno, errorMessage);
    229   if (XML_GetErrorCode(g_parser) != errorCode)
    230     _xml_failure(g_parser, file, lineno);
    231 }
    232 
    233 void
    234 _run_character_check(const char *text, const XML_Char *expected,
    235                      const char *file, int line) {
    236   CharData storage;
    237 
    238   CharData_Init(&storage);
    239   XML_SetUserData(g_parser, &storage);
    240   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
    241   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
    242       == XML_STATUS_ERROR)
    243     _xml_failure(g_parser, file, line);
    244   CharData_CheckXMLChars(&storage, expected);
    245 }
    246 
    247 void
    248 _run_attribute_check(const char *text, const XML_Char *expected,
    249                      const char *file, int line) {
    250   CharData storage;
    251 
    252   CharData_Init(&storage);
    253   XML_SetUserData(g_parser, &storage);
    254   XML_SetStartElementHandler(g_parser, accumulate_attribute);
    255   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
    256       == XML_STATUS_ERROR)
    257     _xml_failure(g_parser, file, line);
    258   CharData_CheckXMLChars(&storage, expected);
    259 }
    260 
    261 void
    262 _run_ext_character_check(const char *text, ExtTest *test_data,
    263                          const XML_Char *expected, const char *file, int line) {
    264   CharData *const storage = (CharData *)malloc(sizeof(CharData));
    265 
    266   CharData_Init(storage);
    267   test_data->storage = storage;
    268   XML_SetUserData(g_parser, test_data);
    269   XML_SetCharacterDataHandler(g_parser, ext_accumulate_characters);
    270   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
    271       == XML_STATUS_ERROR)
    272     _xml_failure(g_parser, file, line);
    273   CharData_CheckXMLChars(storage, expected);
    274 
    275   free(storage);
    276 }
    277 
    278 /* Control variable; the number of times duff_allocator() will successfully
    279  * allocate */
    280 #define ALLOC_ALWAYS_SUCCEED (-1)
    281 #define REALLOC_ALWAYS_SUCCEED (-1)
    282 
    283 int g_allocation_count = ALLOC_ALWAYS_SUCCEED;
    284 int g_reallocation_count = REALLOC_ALWAYS_SUCCEED;
    285 
    286 /* Crocked allocator for allocation failure tests */
    287 void *
    288 duff_allocator(size_t size) {
    289   if (g_allocation_count == 0)
    290     return NULL;
    291   if (g_allocation_count != ALLOC_ALWAYS_SUCCEED)
    292     g_allocation_count--;
    293   return malloc(size);
    294 }
    295 
    296 /* Crocked reallocator for allocation failure tests */
    297 void *
    298 duff_reallocator(void *ptr, size_t size) {
    299   if (g_reallocation_count == 0)
    300     return NULL;
    301   if (g_reallocation_count != REALLOC_ALWAYS_SUCCEED)
    302     g_reallocation_count--;
    303   return realloc(ptr, size);
    304 }
    305 
    306 // Portable remake of strndup(3) for C99; does not care about space efficiency
    307 char *
    308 portable_strndup(const char *s, size_t n) {
    309   if ((s == NULL) || (n == SIZE_MAX)) {
    310     errno = EINVAL;
    311     return NULL;
    312   }
    313 
    314   char *const buffer = (char *)malloc(n + 1);
    315   if (buffer == NULL) {
    316     errno = ENOMEM;
    317     return NULL;
    318   }
    319 
    320   errno = 0;
    321 
    322   memcpy(buffer, s, n);
    323 
    324   buffer[n] = '\0';
    325 
    326   return buffer;
    327 }
    328